2 #include "structmember.h"
5 #define GET_WEAKREFS_LISTPTR(o) \
6 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
10 _PyWeakref_GetWeakrefCount(PyWeakReference
*head
)
14 while (head
!= NULL
) {
23 init_weakref(PyWeakReference
*self
, PyObject
*ob
, PyObject
*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
);
38 init_weakref(result
, ob
, callback
);
39 PyObject_GC_Track(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.
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
));
60 *list
= self
->wr_next
;
61 self
->wr_object
= Py_None
;
62 if (self
->wr_prev
!= NULL
)
63 self
->wr_prev
->wr_next
= self
->wr_next
;
64 if (self
->wr_next
!= NULL
)
65 self
->wr_next
->wr_prev
= self
->wr_prev
;
69 if (callback
!= NULL
) {
71 self
->wr_callback
= NULL
;
75 /* Cyclic gc uses this to *just* clear the passed-in reference, leaving
76 * the callback intact and uncalled. It must be possible to call self's
77 * tp_dealloc() after calling this, so self has to be left in a sane enough
78 * state for that to work. We expect tp_dealloc to decref the callback
79 * then. The reason for not letting clear_weakref() decref the callback
80 * right now is that if the callback goes away, that may in turn trigger
81 * another callback (if a weak reference to the callback exists) -- running
82 * arbitrary Python code in the middle of gc is a disaster. The convolution
83 * here allows gc to delay triggering such callbacks until the world is in
87 _PyWeakref_ClearRef(PyWeakReference
*self
)
92 assert(PyWeakref_Check(self
));
93 /* Preserve and restore the callback around clear_weakref. */
94 callback
= self
->wr_callback
;
95 self
->wr_callback
= NULL
;
97 self
->wr_callback
= callback
;
101 weakref_dealloc(PyObject
*self
)
103 PyObject_GC_UnTrack(self
);
104 clear_weakref((PyWeakReference
*) self
);
105 self
->ob_type
->tp_free(self
);
110 gc_traverse(PyWeakReference
*self
, visitproc visit
, void *arg
)
112 Py_VISIT(self
->wr_callback
);
118 gc_clear(PyWeakReference
*self
)
126 weakref_call(PyWeakReference
*self
, PyObject
*args
, PyObject
*kw
)
128 static char *kwlist
[] = {NULL
};
130 if (PyArg_ParseTupleAndKeywords(args
, kw
, ":__call__", kwlist
)) {
131 PyObject
*object
= PyWeakref_GET_OBJECT(self
);
140 weakref_hash(PyWeakReference
*self
)
142 if (self
->hash
!= -1)
144 if (PyWeakref_GET_OBJECT(self
) == Py_None
) {
145 PyErr_SetString(PyExc_TypeError
, "weak object has gone away");
148 self
->hash
= PyObject_Hash(PyWeakref_GET_OBJECT(self
));
154 weakref_repr(PyWeakReference
*self
)
157 if (PyWeakref_GET_OBJECT(self
) == Py_None
) {
158 PyOS_snprintf(buffer
, sizeof(buffer
), "<weakref at %p; dead>", self
);
162 PyObject
*nameobj
= PyObject_GetAttrString(PyWeakref_GET_OBJECT(self
),
166 else if (PyString_Check(nameobj
))
167 name
= PyString_AS_STRING(nameobj
);
168 PyOS_snprintf(buffer
, sizeof(buffer
),
169 name
? "<weakref at %p; to '%.50s' at %p (%s)>"
170 : "<weakref at %p; to '%.50s' at %p>",
172 PyWeakref_GET_OBJECT(self
)->ob_type
->tp_name
,
173 PyWeakref_GET_OBJECT(self
),
177 return PyString_FromString(buffer
);
180 /* Weak references only support equality, not ordering. Two weak references
181 are equal if the underlying objects are equal. If the underlying object has
182 gone away, they are equal if they are identical. */
185 weakref_richcompare(PyWeakReference
* self
, PyWeakReference
* other
, int op
)
187 if (op
!= Py_EQ
|| self
->ob_type
!= other
->ob_type
) {
188 Py_INCREF(Py_NotImplemented
);
189 return Py_NotImplemented
;
191 if (PyWeakref_GET_OBJECT(self
) == Py_None
192 || PyWeakref_GET_OBJECT(other
) == Py_None
) {
193 PyObject
*res
= self
==other
? Py_True
: Py_False
;
197 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self
),
198 PyWeakref_GET_OBJECT(other
), op
);
201 /* Given the head of an object's list of weak references, extract the
202 * two callback-less refs (ref and proxy). Used to determine if the
203 * shared references exist and to determine the back link for newly
204 * inserted references.
207 get_basic_refs(PyWeakReference
*head
,
208 PyWeakReference
**refp
, PyWeakReference
**proxyp
)
213 if (head
!= NULL
&& head
->wr_callback
== NULL
) {
214 /* We need to be careful that the "basic refs" aren't
215 subclasses of the main types. That complicates this a
217 if (PyWeakref_CheckRefExact(head
)) {
219 head
= head
->wr_next
;
222 && head
->wr_callback
== NULL
223 && PyWeakref_CheckProxy(head
)) {
225 /* head = head->wr_next; */
230 /* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
232 insert_after(PyWeakReference
*newref
, PyWeakReference
*prev
)
234 newref
->wr_prev
= prev
;
235 newref
->wr_next
= prev
->wr_next
;
236 if (prev
->wr_next
!= NULL
)
237 prev
->wr_next
->wr_prev
= newref
;
238 prev
->wr_next
= newref
;
241 /* Insert 'newref' at the head of the list; 'list' points to the variable
242 * that stores the head.
245 insert_head(PyWeakReference
*newref
, PyWeakReference
**list
)
247 PyWeakReference
*next
= *list
;
249 newref
->wr_prev
= NULL
;
250 newref
->wr_next
= next
;
252 next
->wr_prev
= newref
;
257 parse_weakref_init_args(char *funcname
, PyObject
*args
, PyObject
*kwargs
,
258 PyObject
**obp
, PyObject
**callbackp
)
260 /* XXX Should check that kwargs == NULL or is empty. */
261 return PyArg_UnpackTuple(args
, funcname
, 1, 2, obp
, callbackp
);
265 weakref___new__(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwargs
)
267 PyWeakReference
*self
= NULL
;
268 PyObject
*ob
, *callback
= NULL
;
270 if (parse_weakref_init_args("__new__", args
, kwargs
, &ob
, &callback
)) {
271 PyWeakReference
*ref
, *proxy
;
272 PyWeakReference
**list
;
274 if (!PyType_SUPPORTS_WEAKREFS(ob
->ob_type
)) {
275 PyErr_Format(PyExc_TypeError
,
276 "cannot create weak reference to '%s' object",
277 ob
->ob_type
->tp_name
);
280 if (callback
== Py_None
)
282 list
= GET_WEAKREFS_LISTPTR(ob
);
283 get_basic_refs(*list
, &ref
, &proxy
);
284 if (callback
== NULL
&& type
== &_PyWeakref_RefType
) {
286 /* We can re-use an existing reference. */
288 return (PyObject
*)ref
;
291 /* We have to create a new reference. */
292 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
293 list on ob can be mutated. This means that the ref and
294 proxy pointers we got back earlier may have been collected,
295 so we need to compute these values again before we use
297 self
= (PyWeakReference
*) (type
->tp_alloc(type
, 0));
299 init_weakref(self
, ob
, callback
);
300 if (callback
== NULL
&& type
== &_PyWeakref_RefType
) {
301 insert_head(self
, list
);
304 PyWeakReference
*prev
;
306 get_basic_refs(*list
, &ref
, &proxy
);
307 prev
= (proxy
== NULL
) ? ref
: proxy
;
309 insert_head(self
, list
);
311 insert_after(self
, prev
);
315 return (PyObject
*)self
;
319 weakref___init__(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
323 if (parse_weakref_init_args("__init__", args
, kwargs
, &tmp
, &tmp
))
331 _PyWeakref_RefType
= {
332 PyObject_HEAD_INIT(&PyType_Type
)
335 sizeof(PyWeakReference
),
337 weakref_dealloc
, /*tp_dealloc*/
342 (reprfunc
)weakref_repr
, /*tp_repr*/
344 0, /*tp_as_sequence*/
346 (hashfunc
)weakref_hash
, /*tp_hash*/
347 (ternaryfunc
)weakref_call
, /*tp_call*/
352 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_HAVE_RICHCOMPARE
353 | Py_TPFLAGS_BASETYPE
, /*tp_flags*/
355 (traverseproc
)gc_traverse
, /*tp_traverse*/
356 (inquiry
)gc_clear
, /*tp_clear*/
357 (richcmpfunc
)weakref_richcompare
, /*tp_richcompare*/
358 0, /*tp_weaklistoffset*/
369 weakref___init__
, /*tp_init*/
370 PyType_GenericAlloc
, /*tp_alloc*/
371 weakref___new__
, /*tp_new*/
372 PyObject_GC_Del
, /*tp_free*/
377 proxy_checkref(PyWeakReference
*proxy
)
379 if (PyWeakref_GET_OBJECT(proxy
) == Py_None
) {
380 PyErr_SetString(PyExc_ReferenceError
,
381 "weakly-referenced object no longer exists");
388 /* If a parameter is a proxy, check that it is still "live" and wrap it,
389 * replacing the original value with the raw object. Raises ReferenceError
390 * if the param is a dead proxy.
393 if (PyWeakref_CheckProxy(o)) { \
394 if (!proxy_checkref((PyWeakReference *)o)) \
396 o = PyWeakref_GET_OBJECT(o); \
399 #define UNWRAP_I(o) \
400 if (PyWeakref_CheckProxy(o)) { \
401 if (!proxy_checkref((PyWeakReference *)o)) \
403 o = PyWeakref_GET_OBJECT(o); \
406 #define WRAP_UNARY(method, generic) \
408 method(PyObject *proxy) { \
410 return generic(proxy); \
413 #define WRAP_BINARY(method, generic) \
415 method(PyObject *x, PyObject *y) { \
418 return generic(x, y); \
421 /* Note that the third arg needs to be checked for NULL since the tp_call
422 * slot can receive NULL for this arg.
424 #define WRAP_TERNARY(method, generic) \
426 method(PyObject *proxy, PyObject *v, PyObject *w) { \
431 return generic(proxy, v, w); \
437 WRAP_BINARY(proxy_getattr
, PyObject_GetAttr
)
438 WRAP_UNARY(proxy_str
, PyObject_Str
)
439 WRAP_TERNARY(proxy_call
, PyEval_CallObjectWithKeywords
)
442 proxy_repr(PyWeakReference
*proxy
)
445 PyOS_snprintf(buf
, sizeof(buf
),
446 "<weakproxy at %p to %.100s at %p>", proxy
,
447 PyWeakref_GET_OBJECT(proxy
)->ob_type
->tp_name
,
448 PyWeakref_GET_OBJECT(proxy
));
449 return PyString_FromString(buf
);
454 proxy_setattr(PyWeakReference
*proxy
, PyObject
*name
, PyObject
*value
)
456 if (!proxy_checkref(proxy
))
458 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy
), name
, value
);
462 proxy_compare(PyObject
*proxy
, PyObject
*v
)
466 return PyObject_Compare(proxy
, v
);
470 WRAP_BINARY(proxy_add
, PyNumber_Add
)
471 WRAP_BINARY(proxy_sub
, PyNumber_Subtract
)
472 WRAP_BINARY(proxy_mul
, PyNumber_Multiply
)
473 WRAP_BINARY(proxy_div
, PyNumber_Divide
)
474 WRAP_BINARY(proxy_mod
, PyNumber_Remainder
)
475 WRAP_BINARY(proxy_divmod
, PyNumber_Divmod
)
476 WRAP_TERNARY(proxy_pow
, PyNumber_Power
)
477 WRAP_UNARY(proxy_neg
, PyNumber_Negative
)
478 WRAP_UNARY(proxy_pos
, PyNumber_Positive
)
479 WRAP_UNARY(proxy_abs
, PyNumber_Absolute
)
480 WRAP_UNARY(proxy_invert
, PyNumber_Invert
)
481 WRAP_BINARY(proxy_lshift
, PyNumber_Lshift
)
482 WRAP_BINARY(proxy_rshift
, PyNumber_Rshift
)
483 WRAP_BINARY(proxy_and
, PyNumber_And
)
484 WRAP_BINARY(proxy_xor
, PyNumber_Xor
)
485 WRAP_BINARY(proxy_or
, PyNumber_Or
)
486 WRAP_UNARY(proxy_int
, PyNumber_Int
)
487 WRAP_UNARY(proxy_long
, PyNumber_Long
)
488 WRAP_UNARY(proxy_float
, PyNumber_Float
)
489 WRAP_BINARY(proxy_iadd
, PyNumber_InPlaceAdd
)
490 WRAP_BINARY(proxy_isub
, PyNumber_InPlaceSubtract
)
491 WRAP_BINARY(proxy_imul
, PyNumber_InPlaceMultiply
)
492 WRAP_BINARY(proxy_idiv
, PyNumber_InPlaceDivide
)
493 WRAP_BINARY(proxy_imod
, PyNumber_InPlaceRemainder
)
494 WRAP_TERNARY(proxy_ipow
, PyNumber_InPlacePower
)
495 WRAP_BINARY(proxy_ilshift
, PyNumber_InPlaceLshift
)
496 WRAP_BINARY(proxy_irshift
, PyNumber_InPlaceRshift
)
497 WRAP_BINARY(proxy_iand
, PyNumber_InPlaceAnd
)
498 WRAP_BINARY(proxy_ixor
, PyNumber_InPlaceXor
)
499 WRAP_BINARY(proxy_ior
, PyNumber_InPlaceOr
)
502 proxy_nonzero(PyWeakReference
*proxy
)
504 PyObject
*o
= PyWeakref_GET_OBJECT(proxy
);
505 if (!proxy_checkref(proxy
))
507 return PyObject_IsTrue(o
);
511 proxy_dealloc(PyWeakReference
*self
)
513 if (self
->wr_callback
!= NULL
)
514 PyObject_GC_UnTrack((PyObject
*)self
);
516 PyObject_GC_Del(self
);
522 proxy_slice(PyWeakReference
*proxy
, Py_ssize_t i
, Py_ssize_t j
)
524 if (!proxy_checkref(proxy
))
526 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy
), i
, j
);
530 proxy_ass_slice(PyWeakReference
*proxy
, Py_ssize_t i
, Py_ssize_t j
, PyObject
*value
)
532 if (!proxy_checkref(proxy
))
534 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy
), i
, j
, value
);
538 proxy_contains(PyWeakReference
*proxy
, PyObject
*value
)
540 if (!proxy_checkref(proxy
))
542 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy
), value
);
549 proxy_length(PyWeakReference
*proxy
)
551 if (!proxy_checkref(proxy
))
553 return PyObject_Length(PyWeakref_GET_OBJECT(proxy
));
556 WRAP_BINARY(proxy_getitem
, PyObject_GetItem
)
559 proxy_setitem(PyWeakReference
*proxy
, PyObject
*key
, PyObject
*value
)
561 if (!proxy_checkref(proxy
))
565 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy
), key
);
567 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy
), key
, value
);
573 proxy_iter(PyWeakReference
*proxy
)
575 if (!proxy_checkref(proxy
))
577 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy
));
581 proxy_iternext(PyWeakReference
*proxy
)
583 if (!proxy_checkref(proxy
))
585 return PyIter_Next(PyWeakref_GET_OBJECT(proxy
));
589 static PyNumberMethods proxy_as_number
= {
590 proxy_add
, /*nb_add*/
591 proxy_sub
, /*nb_subtract*/
592 proxy_mul
, /*nb_multiply*/
593 proxy_div
, /*nb_divide*/
594 proxy_mod
, /*nb_remainder*/
595 proxy_divmod
, /*nb_divmod*/
596 proxy_pow
, /*nb_power*/
597 proxy_neg
, /*nb_negative*/
598 proxy_pos
, /*nb_positive*/
599 proxy_abs
, /*nb_absolute*/
600 (inquiry
)proxy_nonzero
, /*nb_nonzero*/
601 proxy_invert
, /*nb_invert*/
602 proxy_lshift
, /*nb_lshift*/
603 proxy_rshift
, /*nb_rshift*/
604 proxy_and
, /*nb_and*/
605 proxy_xor
, /*nb_xor*/
608 proxy_int
, /*nb_int*/
609 proxy_long
, /*nb_long*/
610 proxy_float
, /*nb_float*/
613 proxy_iadd
, /*nb_inplace_add*/
614 proxy_isub
, /*nb_inplace_subtract*/
615 proxy_imul
, /*nb_inplace_multiply*/
616 proxy_idiv
, /*nb_inplace_divide*/
617 proxy_imod
, /*nb_inplace_remainder*/
618 proxy_ipow
, /*nb_inplace_power*/
619 proxy_ilshift
, /*nb_inplace_lshift*/
620 proxy_irshift
, /*nb_inplace_rshift*/
621 proxy_iand
, /*nb_inplace_and*/
622 proxy_ixor
, /*nb_inplace_xor*/
623 proxy_ior
, /*nb_inplace_or*/
626 static PySequenceMethods proxy_as_sequence
= {
627 (lenfunc
)proxy_length
, /*sq_length*/
631 (ssizessizeargfunc
)proxy_slice
, /*sq_slice*/
633 (ssizessizeobjargproc
)proxy_ass_slice
, /*sq_ass_slice*/
634 (objobjproc
)proxy_contains
, /* sq_contains */
637 static PyMappingMethods proxy_as_mapping
= {
638 (lenfunc
)proxy_length
, /*mp_length*/
639 proxy_getitem
, /*mp_subscript*/
640 (objobjargproc
)proxy_setitem
, /*mp_ass_subscript*/
645 _PyWeakref_ProxyType
= {
646 PyObject_HEAD_INIT(&PyType_Type
)
649 sizeof(PyWeakReference
),
652 (destructor
)proxy_dealloc
, /* tp_dealloc */
656 proxy_compare
, /* tp_compare */
657 (reprfunc
)proxy_repr
, /* tp_repr */
658 &proxy_as_number
, /* tp_as_number */
659 &proxy_as_sequence
, /* tp_as_sequence */
660 &proxy_as_mapping
, /* tp_as_mapping */
663 proxy_str
, /* tp_str */
664 proxy_getattr
, /* tp_getattro */
665 (setattrofunc
)proxy_setattr
, /* tp_setattro */
666 0, /* tp_as_buffer */
667 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
668 | Py_TPFLAGS_CHECKTYPES
, /* tp_flags */
670 (traverseproc
)gc_traverse
, /* tp_traverse */
671 (inquiry
)gc_clear
, /* tp_clear */
672 0, /* tp_richcompare */
673 0, /* tp_weaklistoffset */
674 (getiterfunc
)proxy_iter
, /* tp_iter */
675 (iternextfunc
)proxy_iternext
, /* tp_iternext */
680 _PyWeakref_CallableProxyType
= {
681 PyObject_HEAD_INIT(&PyType_Type
)
684 sizeof(PyWeakReference
),
687 (destructor
)proxy_dealloc
, /* tp_dealloc */
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 */
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 */
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 */
716 PyWeakref_NewRef(PyObject
*ob
, PyObject
*callback
)
718 PyWeakReference
*result
= NULL
;
719 PyWeakReference
**list
;
720 PyWeakReference
*ref
, *proxy
;
722 if (!PyType_SUPPORTS_WEAKREFS(ob
->ob_type
)) {
723 PyErr_Format(PyExc_TypeError
,
724 "cannot create weak reference to '%s' object",
725 ob
->ob_type
->tp_name
);
728 list
= GET_WEAKREFS_LISTPTR(ob
);
729 get_basic_refs(*list
, &ref
, &proxy
);
730 if (callback
== Py_None
)
732 if (callback
== NULL
)
733 /* return existing weak reference if it exists */
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
743 result
= new_weakref(ob
, callback
);
744 if (result
!= NULL
) {
745 get_basic_refs(*list
, &ref
, &proxy
);
746 if (callback
== NULL
) {
748 insert_head(result
, list
);
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. */
760 PyWeakReference
*prev
;
762 prev
= (proxy
== NULL
) ? ref
: proxy
;
764 insert_head(result
, list
);
766 insert_after(result
, prev
);
770 return (PyObject
*) result
;
775 PyWeakref_NewProxy(PyObject
*ob
, PyObject
*callback
)
777 PyWeakReference
*result
= NULL
;
778 PyWeakReference
**list
;
779 PyWeakReference
*ref
, *proxy
;
781 if (!PyType_SUPPORTS_WEAKREFS(ob
->ob_type
)) {
782 PyErr_Format(PyExc_TypeError
,
783 "cannot create weak reference to '%s' object",
784 ob
->ob_type
->tp_name
);
787 list
= GET_WEAKREFS_LISTPTR(ob
);
788 get_basic_refs(*list
, &ref
, &proxy
);
789 if (callback
== Py_None
)
791 if (callback
== NULL
)
792 /* attempt to return an existing weak reference if it exists */
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
802 result
= new_weakref(ob
, callback
);
803 if (result
!= NULL
) {
804 PyWeakReference
*prev
;
806 if (PyCallable_Check(ob
))
807 result
->ob_type
= &_PyWeakref_CallableProxyType
;
809 result
->ob_type
= &_PyWeakref_ProxyType
;
810 get_basic_refs(*list
, &ref
, &proxy
);
811 if (callback
== 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. */
818 Py_INCREF(result
= proxy
);
824 prev
= (proxy
== NULL
) ? ref
: proxy
;
827 insert_head(result
, list
);
829 insert_after(result
, prev
);
834 return (PyObject
*) result
;
839 PyWeakref_GetObject(PyObject
*ref
)
841 if (ref
== NULL
|| !PyWeakref_Check(ref
)) {
842 PyErr_BadInternalCall();
845 return PyWeakref_GET_OBJECT(ref
);
848 /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
852 handle_callback(PyWeakReference
*ref
, PyObject
*callback
)
854 PyObject
*cbresult
= PyObject_CallFunctionObjArgs(callback
, ref
, NULL
);
856 if (cbresult
== NULL
)
857 PyErr_WriteUnraisable(callback
);
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
869 PyObject_ClearWeakRefs(PyObject
*object
)
871 PyWeakReference
**list
;
874 || !PyType_SUPPORTS_WEAKREFS(object
->ob_type
)
875 || object
->ob_refcnt
!= 0) {
876 PyErr_BadInternalCall();
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
);
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
;
893 PyErr_Fetch(&err_type
, &err_value
, &err_tb
);
895 PyObject
*callback
= current
->wr_callback
;
897 current
->wr_callback
= NULL
;
898 clear_weakref(current
);
899 if (callback
!= NULL
) {
900 handle_callback(current
, callback
);
908 tuple
= PyTuple_New(count
* 2);
911 PyErr_Fetch(&err_type
, &err_value
, &err_tb
);
915 for (i
= 0; i
< count
; ++i
) {
916 PyWeakReference
*next
= current
->wr_next
;
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
);
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
);
936 PyErr_Restore(err_type
, err_value
, err_tb
);