Change to flush and close logic to fix #1760556.
[python.git] / Objects / weakrefobject.c
blobd26d5d1180867578e48085734ce97b7f9b08003c
1 #include "Python.h"
2 #include "structmember.h"
5 #define GET_WEAKREFS_LISTPTR(o) \
6 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
9 Py_ssize_t
10 _PyWeakref_GetWeakrefCount(PyWeakReference *head)
12 Py_ssize_t count = 0;
14 while (head != NULL) {
15 ++count;
16 head = head->wr_next;
18 return count;
22 static void
23 init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
25 self->hash = -1;
26 self->wr_object = ob;
27 Py_XINCREF(callback);
28 self->wr_callback = callback;
31 static PyWeakReference *
32 new_weakref(PyObject *ob, PyObject *callback)
34 PyWeakReference *result;
36 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
37 if (result) {
38 init_weakref(result, ob, callback);
39 PyObject_GC_Track(result);
41 return result;
45 /* This function clears the passed-in reference and removes it from the
46 * list of weak references for the referent. This is the only code that
47 * removes an item from the doubly-linked list of weak references for an
48 * object; it is also responsible for clearing the callback slot.
50 static void
51 clear_weakref(PyWeakReference *self)
53 PyObject *callback = self->wr_callback;
55 if (PyWeakref_GET_OBJECT(self) != Py_None) {
56 PyWeakReference **list = GET_WEAKREFS_LISTPTR(
57 PyWeakref_GET_OBJECT(self));
59 if (*list == self)
60 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
61 then the weakref list itself (and thus the value of *list) will
62 end up being set to NULL. */
63 *list = self->wr_next;
64 self->wr_object = Py_None;
65 if (self->wr_prev != NULL)
66 self->wr_prev->wr_next = self->wr_next;
67 if (self->wr_next != NULL)
68 self->wr_next->wr_prev = self->wr_prev;
69 self->wr_prev = NULL;
70 self->wr_next = NULL;
72 if (callback != NULL) {
73 Py_DECREF(callback);
74 self->wr_callback = NULL;
78 /* Cyclic gc uses this to *just* clear the passed-in reference, leaving
79 * the callback intact and uncalled. It must be possible to call self's
80 * tp_dealloc() after calling this, so self has to be left in a sane enough
81 * state for that to work. We expect tp_dealloc to decref the callback
82 * then. The reason for not letting clear_weakref() decref the callback
83 * right now is that if the callback goes away, that may in turn trigger
84 * another callback (if a weak reference to the callback exists) -- running
85 * arbitrary Python code in the middle of gc is a disaster. The convolution
86 * here allows gc to delay triggering such callbacks until the world is in
87 * a sane state again.
89 void
90 _PyWeakref_ClearRef(PyWeakReference *self)
92 PyObject *callback;
94 assert(self != NULL);
95 assert(PyWeakref_Check(self));
96 /* Preserve and restore the callback around clear_weakref. */
97 callback = self->wr_callback;
98 self->wr_callback = NULL;
99 clear_weakref(self);
100 self->wr_callback = callback;
103 static void
104 weakref_dealloc(PyObject *self)
106 PyObject_GC_UnTrack(self);
107 clear_weakref((PyWeakReference *) self);
108 Py_Type(self)->tp_free(self);
112 static int
113 gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
115 Py_VISIT(self->wr_callback);
116 return 0;
120 static int
121 gc_clear(PyWeakReference *self)
123 clear_weakref(self);
124 return 0;
128 static PyObject *
129 weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
131 static char *kwlist[] = {NULL};
133 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
134 PyObject *object = PyWeakref_GET_OBJECT(self);
135 Py_INCREF(object);
136 return (object);
138 return NULL;
142 static long
143 weakref_hash(PyWeakReference *self)
145 if (self->hash != -1)
146 return self->hash;
147 if (PyWeakref_GET_OBJECT(self) == Py_None) {
148 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
149 return -1;
151 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
152 return self->hash;
156 static PyObject *
157 weakref_repr(PyWeakReference *self)
159 char buffer[256];
160 if (PyWeakref_GET_OBJECT(self) == Py_None) {
161 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
163 else {
164 char *name = NULL;
165 PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
166 "__name__");
167 if (nameobj == NULL)
168 PyErr_Clear();
169 else if (PyString_Check(nameobj))
170 name = PyString_AS_STRING(nameobj);
171 PyOS_snprintf(buffer, sizeof(buffer),
172 name ? "<weakref at %p; to '%.50s' at %p (%s)>"
173 : "<weakref at %p; to '%.50s' at %p>",
174 self,
175 Py_Type(PyWeakref_GET_OBJECT(self))->tp_name,
176 PyWeakref_GET_OBJECT(self),
177 name);
178 Py_XDECREF(nameobj);
180 return PyString_FromString(buffer);
183 /* Weak references only support equality, not ordering. Two weak references
184 are equal if the underlying objects are equal. If the underlying object has
185 gone away, they are equal if they are identical. */
187 static PyObject *
188 weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
190 if (op != Py_EQ || self->ob_type != other->ob_type) {
191 Py_INCREF(Py_NotImplemented);
192 return Py_NotImplemented;
194 if (PyWeakref_GET_OBJECT(self) == Py_None
195 || PyWeakref_GET_OBJECT(other) == Py_None) {
196 PyObject *res = self==other ? Py_True : Py_False;
197 Py_INCREF(res);
198 return res;
200 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
201 PyWeakref_GET_OBJECT(other), op);
204 /* Given the head of an object's list of weak references, extract the
205 * two callback-less refs (ref and proxy). Used to determine if the
206 * shared references exist and to determine the back link for newly
207 * inserted references.
209 static void
210 get_basic_refs(PyWeakReference *head,
211 PyWeakReference **refp, PyWeakReference **proxyp)
213 *refp = NULL;
214 *proxyp = NULL;
216 if (head != NULL && head->wr_callback == NULL) {
217 /* We need to be careful that the "basic refs" aren't
218 subclasses of the main types. That complicates this a
219 little. */
220 if (PyWeakref_CheckRefExact(head)) {
221 *refp = head;
222 head = head->wr_next;
224 if (head != NULL
225 && head->wr_callback == NULL
226 && PyWeakref_CheckProxy(head)) {
227 *proxyp = head;
228 /* head = head->wr_next; */
233 /* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
234 static void
235 insert_after(PyWeakReference *newref, PyWeakReference *prev)
237 newref->wr_prev = prev;
238 newref->wr_next = prev->wr_next;
239 if (prev->wr_next != NULL)
240 prev->wr_next->wr_prev = newref;
241 prev->wr_next = newref;
244 /* Insert 'newref' at the head of the list; 'list' points to the variable
245 * that stores the head.
247 static void
248 insert_head(PyWeakReference *newref, PyWeakReference **list)
250 PyWeakReference *next = *list;
252 newref->wr_prev = NULL;
253 newref->wr_next = next;
254 if (next != NULL)
255 next->wr_prev = newref;
256 *list = newref;
259 static int
260 parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
261 PyObject **obp, PyObject **callbackp)
263 /* XXX Should check that kwargs == NULL or is empty. */
264 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
267 static PyObject *
268 weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
270 PyWeakReference *self = NULL;
271 PyObject *ob, *callback = NULL;
273 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
274 PyWeakReference *ref, *proxy;
275 PyWeakReference **list;
277 if (!PyType_SUPPORTS_WEAKREFS(Py_Type(ob))) {
278 PyErr_Format(PyExc_TypeError,
279 "cannot create weak reference to '%s' object",
280 Py_Type(ob)->tp_name);
281 return NULL;
283 if (callback == Py_None)
284 callback = NULL;
285 list = GET_WEAKREFS_LISTPTR(ob);
286 get_basic_refs(*list, &ref, &proxy);
287 if (callback == NULL && type == &_PyWeakref_RefType) {
288 if (ref != NULL) {
289 /* We can re-use an existing reference. */
290 Py_INCREF(ref);
291 return (PyObject *)ref;
294 /* We have to create a new reference. */
295 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
296 list on ob can be mutated. This means that the ref and
297 proxy pointers we got back earlier may have been collected,
298 so we need to compute these values again before we use
299 them. */
300 self = (PyWeakReference *) (type->tp_alloc(type, 0));
301 if (self != NULL) {
302 init_weakref(self, ob, callback);
303 if (callback == NULL && type == &_PyWeakref_RefType) {
304 insert_head(self, list);
306 else {
307 PyWeakReference *prev;
309 get_basic_refs(*list, &ref, &proxy);
310 prev = (proxy == NULL) ? ref : proxy;
311 if (prev == NULL)
312 insert_head(self, list);
313 else
314 insert_after(self, prev);
318 return (PyObject *)self;
321 static int
322 weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
324 PyObject *tmp;
326 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
327 return 0;
328 else
329 return 1;
333 PyTypeObject
334 _PyWeakref_RefType = {
335 PyVarObject_HEAD_INIT(&PyType_Type, 0)
336 "weakref",
337 sizeof(PyWeakReference),
339 weakref_dealloc, /*tp_dealloc*/
340 0, /*tp_print*/
341 0, /*tp_getattr*/
342 0, /*tp_setattr*/
343 0, /*tp_compare*/
344 (reprfunc)weakref_repr, /*tp_repr*/
345 0, /*tp_as_number*/
346 0, /*tp_as_sequence*/
347 0, /*tp_as_mapping*/
348 (hashfunc)weakref_hash, /*tp_hash*/
349 (ternaryfunc)weakref_call, /*tp_call*/
350 0, /*tp_str*/
351 0, /*tp_getattro*/
352 0, /*tp_setattro*/
353 0, /*tp_as_buffer*/
354 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
355 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
356 0, /*tp_doc*/
357 (traverseproc)gc_traverse, /*tp_traverse*/
358 (inquiry)gc_clear, /*tp_clear*/
359 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
360 0, /*tp_weaklistoffset*/
361 0, /*tp_iter*/
362 0, /*tp_iternext*/
363 0, /*tp_methods*/
364 0, /*tp_members*/
365 0, /*tp_getset*/
366 0, /*tp_base*/
367 0, /*tp_dict*/
368 0, /*tp_descr_get*/
369 0, /*tp_descr_set*/
370 0, /*tp_dictoffset*/
371 weakref___init__, /*tp_init*/
372 PyType_GenericAlloc, /*tp_alloc*/
373 weakref___new__, /*tp_new*/
374 PyObject_GC_Del, /*tp_free*/
378 static int
379 proxy_checkref(PyWeakReference *proxy)
381 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
382 PyErr_SetString(PyExc_ReferenceError,
383 "weakly-referenced object no longer exists");
384 return 0;
386 return 1;
390 /* If a parameter is a proxy, check that it is still "live" and wrap it,
391 * replacing the original value with the raw object. Raises ReferenceError
392 * if the param is a dead proxy.
394 #define UNWRAP(o) \
395 if (PyWeakref_CheckProxy(o)) { \
396 if (!proxy_checkref((PyWeakReference *)o)) \
397 return NULL; \
398 o = PyWeakref_GET_OBJECT(o); \
401 #define UNWRAP_I(o) \
402 if (PyWeakref_CheckProxy(o)) { \
403 if (!proxy_checkref((PyWeakReference *)o)) \
404 return -1; \
405 o = PyWeakref_GET_OBJECT(o); \
408 #define WRAP_UNARY(method, generic) \
409 static PyObject * \
410 method(PyObject *proxy) { \
411 UNWRAP(proxy); \
412 return generic(proxy); \
415 #define WRAP_BINARY(method, generic) \
416 static PyObject * \
417 method(PyObject *x, PyObject *y) { \
418 UNWRAP(x); \
419 UNWRAP(y); \
420 return generic(x, y); \
423 /* Note that the third arg needs to be checked for NULL since the tp_call
424 * slot can receive NULL for this arg.
426 #define WRAP_TERNARY(method, generic) \
427 static PyObject * \
428 method(PyObject *proxy, PyObject *v, PyObject *w) { \
429 UNWRAP(proxy); \
430 UNWRAP(v); \
431 if (w != NULL) \
432 UNWRAP(w); \
433 return generic(proxy, v, w); \
437 /* direct slots */
439 WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
440 WRAP_UNARY(proxy_str, PyObject_Str)
441 WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
443 static PyObject *
444 proxy_repr(PyWeakReference *proxy)
446 char buf[160];
447 PyOS_snprintf(buf, sizeof(buf),
448 "<weakproxy at %p to %.100s at %p>", proxy,
449 Py_Type(PyWeakref_GET_OBJECT(proxy))->tp_name,
450 PyWeakref_GET_OBJECT(proxy));
451 return PyString_FromString(buf);
455 static int
456 proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
458 if (!proxy_checkref(proxy))
459 return -1;
460 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
463 static int
464 proxy_compare(PyObject *proxy, PyObject *v)
466 UNWRAP_I(proxy);
467 UNWRAP_I(v);
468 return PyObject_Compare(proxy, v);
471 /* number slots */
472 WRAP_BINARY(proxy_add, PyNumber_Add)
473 WRAP_BINARY(proxy_sub, PyNumber_Subtract)
474 WRAP_BINARY(proxy_mul, PyNumber_Multiply)
475 WRAP_BINARY(proxy_div, PyNumber_Divide)
476 WRAP_BINARY(proxy_mod, PyNumber_Remainder)
477 WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
478 WRAP_TERNARY(proxy_pow, PyNumber_Power)
479 WRAP_UNARY(proxy_neg, PyNumber_Negative)
480 WRAP_UNARY(proxy_pos, PyNumber_Positive)
481 WRAP_UNARY(proxy_abs, PyNumber_Absolute)
482 WRAP_UNARY(proxy_invert, PyNumber_Invert)
483 WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
484 WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
485 WRAP_BINARY(proxy_and, PyNumber_And)
486 WRAP_BINARY(proxy_xor, PyNumber_Xor)
487 WRAP_BINARY(proxy_or, PyNumber_Or)
488 WRAP_UNARY(proxy_int, PyNumber_Int)
489 WRAP_UNARY(proxy_long, PyNumber_Long)
490 WRAP_UNARY(proxy_float, PyNumber_Float)
491 WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
492 WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
493 WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
494 WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
495 WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
496 WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
497 WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
498 WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
499 WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
500 WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
501 WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
503 static int
504 proxy_nonzero(PyWeakReference *proxy)
506 PyObject *o = PyWeakref_GET_OBJECT(proxy);
507 if (!proxy_checkref(proxy))
508 return -1;
509 return PyObject_IsTrue(o);
512 static void
513 proxy_dealloc(PyWeakReference *self)
515 if (self->wr_callback != NULL)
516 PyObject_GC_UnTrack((PyObject *)self);
517 clear_weakref(self);
518 PyObject_GC_Del(self);
521 /* sequence slots */
523 static PyObject *
524 proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
526 if (!proxy_checkref(proxy))
527 return NULL;
528 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
531 static int
532 proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
534 if (!proxy_checkref(proxy))
535 return -1;
536 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
539 static int
540 proxy_contains(PyWeakReference *proxy, PyObject *value)
542 if (!proxy_checkref(proxy))
543 return -1;
544 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
548 /* mapping slots */
550 static Py_ssize_t
551 proxy_length(PyWeakReference *proxy)
553 if (!proxy_checkref(proxy))
554 return -1;
555 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
558 WRAP_BINARY(proxy_getitem, PyObject_GetItem)
560 static int
561 proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
563 if (!proxy_checkref(proxy))
564 return -1;
566 if (value == NULL)
567 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
568 else
569 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
572 /* iterator slots */
574 static PyObject *
575 proxy_iter(PyWeakReference *proxy)
577 if (!proxy_checkref(proxy))
578 return NULL;
579 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
582 static PyObject *
583 proxy_iternext(PyWeakReference *proxy)
585 if (!proxy_checkref(proxy))
586 return NULL;
587 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
591 static PyNumberMethods proxy_as_number = {
592 proxy_add, /*nb_add*/
593 proxy_sub, /*nb_subtract*/
594 proxy_mul, /*nb_multiply*/
595 proxy_div, /*nb_divide*/
596 proxy_mod, /*nb_remainder*/
597 proxy_divmod, /*nb_divmod*/
598 proxy_pow, /*nb_power*/
599 proxy_neg, /*nb_negative*/
600 proxy_pos, /*nb_positive*/
601 proxy_abs, /*nb_absolute*/
602 (inquiry)proxy_nonzero, /*nb_nonzero*/
603 proxy_invert, /*nb_invert*/
604 proxy_lshift, /*nb_lshift*/
605 proxy_rshift, /*nb_rshift*/
606 proxy_and, /*nb_and*/
607 proxy_xor, /*nb_xor*/
608 proxy_or, /*nb_or*/
609 0, /*nb_coerce*/
610 proxy_int, /*nb_int*/
611 proxy_long, /*nb_long*/
612 proxy_float, /*nb_float*/
613 0, /*nb_oct*/
614 0, /*nb_hex*/
615 proxy_iadd, /*nb_inplace_add*/
616 proxy_isub, /*nb_inplace_subtract*/
617 proxy_imul, /*nb_inplace_multiply*/
618 proxy_idiv, /*nb_inplace_divide*/
619 proxy_imod, /*nb_inplace_remainder*/
620 proxy_ipow, /*nb_inplace_power*/
621 proxy_ilshift, /*nb_inplace_lshift*/
622 proxy_irshift, /*nb_inplace_rshift*/
623 proxy_iand, /*nb_inplace_and*/
624 proxy_ixor, /*nb_inplace_xor*/
625 proxy_ior, /*nb_inplace_or*/
628 static PySequenceMethods proxy_as_sequence = {
629 (lenfunc)proxy_length, /*sq_length*/
630 0, /*sq_concat*/
631 0, /*sq_repeat*/
632 0, /*sq_item*/
633 (ssizessizeargfunc)proxy_slice, /*sq_slice*/
634 0, /*sq_ass_item*/
635 (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/
636 (objobjproc)proxy_contains, /* sq_contains */
639 static PyMappingMethods proxy_as_mapping = {
640 (lenfunc)proxy_length, /*mp_length*/
641 proxy_getitem, /*mp_subscript*/
642 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
646 PyTypeObject
647 _PyWeakref_ProxyType = {
648 PyVarObject_HEAD_INIT(&PyType_Type, 0)
649 "weakproxy",
650 sizeof(PyWeakReference),
652 /* methods */
653 (destructor)proxy_dealloc, /* tp_dealloc */
654 0, /* tp_print */
655 0, /* tp_getattr */
656 0, /* tp_setattr */
657 proxy_compare, /* tp_compare */
658 (reprfunc)proxy_repr, /* tp_repr */
659 &proxy_as_number, /* tp_as_number */
660 &proxy_as_sequence, /* tp_as_sequence */
661 &proxy_as_mapping, /* tp_as_mapping */
662 0, /* tp_hash */
663 0, /* tp_call */
664 proxy_str, /* tp_str */
665 proxy_getattr, /* tp_getattro */
666 (setattrofunc)proxy_setattr, /* tp_setattro */
667 0, /* tp_as_buffer */
668 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
669 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
670 0, /* tp_doc */
671 (traverseproc)gc_traverse, /* tp_traverse */
672 (inquiry)gc_clear, /* tp_clear */
673 0, /* tp_richcompare */
674 0, /* tp_weaklistoffset */
675 (getiterfunc)proxy_iter, /* tp_iter */
676 (iternextfunc)proxy_iternext, /* tp_iternext */
680 PyTypeObject
681 _PyWeakref_CallableProxyType = {
682 PyVarObject_HEAD_INIT(&PyType_Type, 0)
683 "weakcallableproxy",
684 sizeof(PyWeakReference),
686 /* methods */
687 (destructor)proxy_dealloc, /* tp_dealloc */
688 0, /* tp_print */
689 0, /* tp_getattr */
690 0, /* tp_setattr */
691 proxy_compare, /* tp_compare */
692 (unaryfunc)proxy_repr, /* tp_repr */
693 &proxy_as_number, /* tp_as_number */
694 &proxy_as_sequence, /* tp_as_sequence */
695 &proxy_as_mapping, /* tp_as_mapping */
696 0, /* tp_hash */
697 proxy_call, /* tp_call */
698 proxy_str, /* tp_str */
699 proxy_getattr, /* tp_getattro */
700 (setattrofunc)proxy_setattr, /* tp_setattro */
701 0, /* tp_as_buffer */
702 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
703 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
704 0, /* tp_doc */
705 (traverseproc)gc_traverse, /* tp_traverse */
706 (inquiry)gc_clear, /* tp_clear */
707 0, /* tp_richcompare */
708 0, /* tp_weaklistoffset */
709 (getiterfunc)proxy_iter, /* tp_iter */
710 (iternextfunc)proxy_iternext, /* tp_iternext */
715 PyObject *
716 PyWeakref_NewRef(PyObject *ob, PyObject *callback)
718 PyWeakReference *result = NULL;
719 PyWeakReference **list;
720 PyWeakReference *ref, *proxy;
722 if (!PyType_SUPPORTS_WEAKREFS(Py_Type(ob))) {
723 PyErr_Format(PyExc_TypeError,
724 "cannot create weak reference to '%s' object",
725 Py_Type(ob)->tp_name);
726 return NULL;
728 list = GET_WEAKREFS_LISTPTR(ob);
729 get_basic_refs(*list, &ref, &proxy);
730 if (callback == Py_None)
731 callback = NULL;
732 if (callback == NULL)
733 /* return existing weak reference if it exists */
734 result = ref;
735 if (result != NULL)
736 Py_INCREF(result);
737 else {
738 /* Note: new_weakref() can trigger cyclic GC, so the weakref
739 list on ob can be mutated. This means that the ref and
740 proxy pointers we got back earlier may have been collected,
741 so we need to compute these values again before we use
742 them. */
743 result = new_weakref(ob, callback);
744 if (result != NULL) {
745 get_basic_refs(*list, &ref, &proxy);
746 if (callback == NULL) {
747 if (ref == NULL)
748 insert_head(result, list);
749 else {
750 /* Someone else added a ref without a callback
751 during GC. Return that one instead of this one
752 to avoid violating the invariants of the list
753 of weakrefs for ob. */
754 Py_DECREF(result);
755 Py_INCREF(ref);
756 result = ref;
759 else {
760 PyWeakReference *prev;
762 prev = (proxy == NULL) ? ref : proxy;
763 if (prev == NULL)
764 insert_head(result, list);
765 else
766 insert_after(result, prev);
770 return (PyObject *) result;
774 PyObject *
775 PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
777 PyWeakReference *result = NULL;
778 PyWeakReference **list;
779 PyWeakReference *ref, *proxy;
781 if (!PyType_SUPPORTS_WEAKREFS(Py_Type(ob))) {
782 PyErr_Format(PyExc_TypeError,
783 "cannot create weak reference to '%s' object",
784 Py_Type(ob)->tp_name);
785 return NULL;
787 list = GET_WEAKREFS_LISTPTR(ob);
788 get_basic_refs(*list, &ref, &proxy);
789 if (callback == Py_None)
790 callback = NULL;
791 if (callback == NULL)
792 /* attempt to return an existing weak reference if it exists */
793 result = proxy;
794 if (result != NULL)
795 Py_INCREF(result);
796 else {
797 /* Note: new_weakref() can trigger cyclic GC, so the weakref
798 list on ob can be mutated. This means that the ref and
799 proxy pointers we got back earlier may have been collected,
800 so we need to compute these values again before we use
801 them. */
802 result = new_weakref(ob, callback);
803 if (result != NULL) {
804 PyWeakReference *prev;
806 if (PyCallable_Check(ob))
807 Py_Type(result) = &_PyWeakref_CallableProxyType;
808 else
809 Py_Type(result) = &_PyWeakref_ProxyType;
810 get_basic_refs(*list, &ref, &proxy);
811 if (callback == NULL) {
812 if (proxy != NULL) {
813 /* Someone else added a proxy without a callback
814 during GC. Return that one instead of this one
815 to avoid violating the invariants of the list
816 of weakrefs for ob. */
817 Py_DECREF(result);
818 Py_INCREF(result = proxy);
819 goto skip_insert;
821 prev = ref;
823 else
824 prev = (proxy == NULL) ? ref : proxy;
826 if (prev == NULL)
827 insert_head(result, list);
828 else
829 insert_after(result, prev);
830 skip_insert:
834 return (PyObject *) result;
838 PyObject *
839 PyWeakref_GetObject(PyObject *ref)
841 if (ref == NULL || !PyWeakref_Check(ref)) {
842 PyErr_BadInternalCall();
843 return NULL;
845 return PyWeakref_GET_OBJECT(ref);
848 /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
849 * handle_weakrefs().
851 static void
852 handle_callback(PyWeakReference *ref, PyObject *callback)
854 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
856 if (cbresult == NULL)
857 PyErr_WriteUnraisable(callback);
858 else
859 Py_DECREF(cbresult);
862 /* This function is called by the tp_dealloc handler to clear weak references.
864 * This iterates through the weak references for 'object' and calls callbacks
865 * for those references which have one. It returns when all callbacks have
866 * been attempted.
868 void
869 PyObject_ClearWeakRefs(PyObject *object)
871 PyWeakReference **list;
873 if (object == NULL
874 || !PyType_SUPPORTS_WEAKREFS(Py_Type(object))
875 || object->ob_refcnt != 0) {
876 PyErr_BadInternalCall();
877 return;
879 list = GET_WEAKREFS_LISTPTR(object);
880 /* Remove the callback-less basic and proxy references */
881 if (*list != NULL && (*list)->wr_callback == NULL) {
882 clear_weakref(*list);
883 if (*list != NULL && (*list)->wr_callback == NULL)
884 clear_weakref(*list);
886 if (*list != NULL) {
887 PyWeakReference *current = *list;
888 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
889 int restore_error = PyErr_Occurred() ? 1 : 0;
890 PyObject *err_type, *err_value, *err_tb;
892 if (restore_error)
893 PyErr_Fetch(&err_type, &err_value, &err_tb);
894 if (count == 1) {
895 PyObject *callback = current->wr_callback;
897 current->wr_callback = NULL;
898 clear_weakref(current);
899 if (callback != NULL) {
900 handle_callback(current, callback);
901 Py_DECREF(callback);
904 else {
905 PyObject *tuple;
906 Py_ssize_t i = 0;
908 tuple = PyTuple_New(count * 2);
909 if (tuple == NULL) {
910 if (restore_error)
911 PyErr_Fetch(&err_type, &err_value, &err_tb);
912 return;
915 for (i = 0; i < count; ++i) {
916 PyWeakReference *next = current->wr_next;
918 Py_INCREF(current);
919 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
920 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
921 current->wr_callback = NULL;
922 clear_weakref(current);
923 current = next;
925 for (i = 0; i < count; ++i) {
926 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
928 if (callback != NULL) {
929 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
930 handle_callback((PyWeakReference *)item, callback);
933 Py_DECREF(tuple);
935 if (restore_error)
936 PyErr_Restore(err_type, err_value, err_tb);