WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr) static intproxy_nonzero(PyWeakReference *proxy){ PyObject *o = PyWeakref_GET_OBJECT(proxy); if (!proxy_checkref(proxy)) return -1; return PyObject_IsTrue(o);} static voidproxy_dealloc(PyWeakReference *self){ if (self->wr_callback != NULL) PyObject_GC_UnTrack((PyObject *)self); clear_weakref(self); PyObject_GC_Del(self);} /* sequence slots */ static PyObject *proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j){ if (!proxy_checkref(proxy)) return NULL; return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);} static intproxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value){ if (!proxy_checkref(proxy)) return -1; return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);} static intproxy_contains(PyWeakReference *proxy, PyObject *value){ if (!proxy_checkref(proxy)) return -1; return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);} /* mapping slots */ static Py_ssize_tproxy_length(PyWeakReference *proxy){ if (!proxy_checkref(proxy)) return -1; return PyObject_Length(PyWeakref_GET_OBJECT(proxy));} WRAP_BINARY(proxy_getitem, PyObject_GetItem) static intproxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value){ if (!proxy_checkref(proxy)) return -1; if (value == NULL) return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key); else return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);} /* iterator slots */ static PyObject *proxy_iter(PyWeakReference *proxy){ if (!proxy_checkref(proxy)) return NULL; return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));} static PyObject *proxy_iternext(PyWeakReference *proxy){ if (!proxy_checkref(proxy)) return NULL; return PyIter_Next(PyWeakref_GET_OBJECT(proxy));} static PyNumberMethods proxy_as_number = { proxy_add, /*nb_add*/ proxy_sub, /*nb_subtract*/ proxy_mul, /*nb_multiply*/ proxy_div, /*nb_divide*/ proxy_mod, /*nb_remainder*/ proxy_divmod, /*nb_divmod*/ proxy_pow, /*nb_power*/ proxy_neg, /*nb_negative*/ proxy_pos, /*nb_positive*/ proxy_abs, /*nb_absolute*/ (inquiry)proxy_nonzero, /*nb_nonzero*/ proxy_invert, /*nb_invert*/ proxy_lshift, /*nb_lshift*/ proxy_rshift, /*nb_rshift*/ proxy_and, /*nb_and*/ proxy_xor, /*nb_xor*/ proxy_or, /*nb_or*/ 0, /*nb_coerce*/ proxy_int, /*nb_int*/ proxy_long, /*nb_long*/ proxy_float, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ proxy_iadd, /*nb_inplace_add*/ proxy_isub, /*nb_inplace_subtract*/ proxy_imul, /*nb_inplace_multiply*/ proxy_idiv, /*nb_inplace_divide*/ proxy_imod, /*nb_inplace_remainder*/ proxy_ipow, /*nb_inplace_power*/ proxy_ilshift, /*nb_inplace_lshift*/ proxy_irshift, /*nb_inplace_rshift*/ proxy_iand, /*nb_inplace_and*/ proxy_ixor, /*nb_inplace_xor*/ proxy_ior, /*nb_inplace_or*/}; static PySequenceMethods proxy_as_sequence = { (lenfunc)proxy_length, /*sq_length*/ 0, /*sq_concat*/ 0, /*sq_repeat*/ 0, /*sq_item*/ (ssizessizeargfunc)proxy_slice, /*sq_slice*/ 0, /*sq_ass_item*/ (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/ (objobjproc)proxy_contains, /* sq_contains */}; static PyMappingMethods proxy_as_mapping = { (lenfunc)proxy_length, /*mp_length*/ proxy_getitem, /*mp_subscript*/ (objobjargproc)proxy_setitem, /*mp_ass_subscript*/}; PyTypeObject_PyWeakref_ProxyType = { PyObject_HEAD_INIT(&PyType_Type) 0, "weakproxy", sizeof(PyWeakReference), 0, /* methods */ (destructor)proxy_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ proxy_compare, /* tp_compare */ (reprfunc)proxy_repr, /* tp_repr */ &proxy_as_number, /* tp_as_number */ &proxy_as_sequence, /* tp_as_sequence */ &proxy_as_mapping, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ proxy_str, /* tp_str */ proxy_getattr, /* tp_getattro */ (setattrofunc)proxy_setattr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ 0, /* tp_doc */ (traverseproc)gc_traverse, /* tp_traverse */ (inquiry)gc_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)proxy_iter, /* tp_iter */ (iternextfunc)proxy_iternext, /* tp_iternext */}; PyTypeObject_PyWeakref_CallableProxyType = { PyObject_HEAD_INIT(&PyType_Type) 0, "weakcallableproxy", sizeof(PyWeakReference), 0, /* methods */ (destructor)proxy_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ proxy_compare, /* tp_compare */ (unaryfunc)proxy_repr, /* tp_repr */ &proxy_as_number, /* tp_as_number */ &proxy_as_sequence, /* tp_as_sequence */ &proxy_as_mapping, /* tp_as_mapping */ 0, /* tp_hash */ proxy_call, /* tp_call */ proxy_str, /* tp_str */ proxy_getattr, /* tp_getattro */ (setattrofunc)proxy_setattr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ 0, /* tp_doc */ (traverseproc)gc_traverse, /* tp_traverse */ (inquiry)gc_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)proxy_iter, /* tp_iter */ (iternextfunc)proxy_iternext, /* tp_iternext */}; PyObject *PyWeakref_NewRef(PyObject *ob, PyObject *callback){ PyWeakReference *result = NULL; PyWeakReference **list; PyWeakReference *ref, *proxy; if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) { PyErr_Format(PyExc_TypeError, "cannot create weak reference to '%s' object", ob->ob_type->tp_name); return NULL; } list = GET_WEAKREFS_LISTPTR(ob); get_basic_refs(*list, &ref, &proxy); if (callback == Py_None) callback = NULL; if (callback == NULL) /* return existing weak reference if it exists */ result = ref; if (result != NULL) Py_INCREF(result); else { /* Note: new_weakref() can trigger cyclic GC, so the weakref list on ob can be mutated. This means that the ref and proxy pointers we got back earlier may have been collected, so we need to compute these values again before we use them. */ result = new_weakref(ob, callback); if (result != NULL) { get_basic_refs(*list, &ref, &proxy); if (callback == NULL) { if (ref == NULL) insert_head(result, list); else { /* Someone else added a ref without a callback during GC. Return that one instead of this one to avoid violating the invariants of the list of weakrefs for ob. */ Py_DECREF(result); Py_INCREF(ref); result = ref; } } else { PyWeakReference *prev; prev = (proxy == NULL) ? ref : proxy; if (prev == NULL) insert_head(result, list); else insert_after(result, prev); } } } return (PyObject *) result;} PyObject *PyWeakref_NewProxy(PyObject *ob, PyObject *callback){ PyWeakReference *result = NULL; PyWeakReference **list; PyWeakReference *ref, *proxy; if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) { PyErr_Format(PyExc_TypeError, "cannot create weak reference to '%s' object", ob->ob_type->tp_name); return NULL; } list = GET_WEAKREFS_LISTPTR(ob); get_basic_refs(*list, &ref, &proxy); if (callback == Py_None) callback = NULL; if (callback == NULL) /* attempt to return an existing weak reference if it exists */ result = proxy; if (result != NULL) Py_INCREF(result); else { /* Note: new_weakref() can trigger cyclic GC, so the weakref list on ob can be mutated. This means that the ref and proxy pointers we got back earlier may have been collected, so we need to compute these values again before we use them. */ result = new_weakref(ob, callback); if (result != NULL) { PyWeakReference *prev; if (PyCallable_Check(ob)) result->ob_type = &_PyWeakref_CallableProxyType; else result->ob_type = &_PyWeakref_ProxyType; get_basic_refs(*list, &ref, &proxy); if (callback == NULL) { if (proxy != NULL) { /* Someone else added a proxy without a callback during GC. Return that one instead of this one to avoid violating the invariants of the list of weakrefs for ob. */ Py_DECREF(result); Py_INCREF(result = proxy); goto skip_insert; } prev = ref; } else prev = (proxy == NULL) ? ref : proxy; if (prev == NULL) insert_head(result, list); else insert_after(result, prev); skip_insert: ; } } return (PyObject *) result;} PyObject *PyWeakref_GetObject(PyObject *ref){ if (ref == NULL || !PyWeakref_Check(ref)) { PyErr_BadInternalCall(); return NULL; } return PyWeakref_GET_OBJECT(ref);} /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's * handle_weakrefs(). */static voidhandle_callback(PyWeakReference *ref, PyObject *callback){ PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL); if (cbresult == NULL) PyErr_WriteUnraisable(callback); else Py_DECREF(cbresult);} /* This function is called by the tp_dealloc handler to clear weak references. * * This iterates through the weak references for 'object' and calls callbacks * for those references which have one. It returns when all callbacks have * been attempted. */voidPyObject_ClearWeakRefs(PyObject *object){ PyWeakReference **list; if (object == NULL || !PyType_SUPPORTS_WEAKREFS(object->ob_type) || object->ob_refcnt != 0) { PyErr_BadInternalCall(); return; } list = GET_WEAKREFS_LISTPTR(object); /* Remove the callback-less basic and proxy references */ if (*list != NULL && (*list)->wr_callback == NULL) { clear_weakref(*list); if (*list != NULL && (*list)->wr_callback == NULL) clear_weakref(*list); } if (*list != NULL) { PyWeakReference *current = *list; Py_ssize_t count = _PyWeakref_GetWeakrefCount(current); int restore_error = PyErr_Occurred() ? 1 : 0; PyObject *err_type, *err_value, *err_tb; if (restore_error) PyErr_Fetch(&err_type, &err_value, &err_tb); if (count == 1) { PyObject *callback = current->wr_callback; current->wr_callback = NULL; clear_weakref(current); if (callback != NULL) { handle_callback(current, callback); Py_DECREF(callback); } } else { PyObject *tuple; Py_ssize_t i = 0; tuple = PyTuple_New(count * 2); if (tuple == NULL) { if (restore_error) PyErr_Fetch(&err_type, &err_value, &err_tb); return; } for (i = 0; i < count; ++i) { PyWeakReference *next = current->wr_next; Py_INCREF(current); PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current); PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback); current->wr_callback = NULL; clear_weakref(current); current = next; } for (i = 0; i < count; ++i) { PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1); if (callback != NULL) { PyObject *item = PyTuple_GET_ITEM(tuple, i * 2); handle_callback((PyWeakReference *)item, callback); } } Py_DECREF(tuple); } if (restore_error) PyErr_Restore(err_type, err_value, err_tb); }}Lines 501–941 of 941. Previous lines
WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor) WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr) static int proxy_nonzero(PyWeakReference *proxy) { PyObject *o = PyWeakref_GET_OBJECT(proxy); if (!proxy_checkref(proxy)) return -1; return PyObject_IsTrue(o); } static void proxy_dealloc(PyWeakReference *self) { if (self->wr_callback != NULL) PyObject_GC_UnTrack((PyObject *)self); clear_weakref(self); PyObject_GC_Del(self); } /* sequence slots */ static PyObject * proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j) { if (!proxy_checkref(proxy)) return NULL; return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j); } static int proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value) { if (!proxy_checkref(proxy)) return -1; return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value); } static int proxy_contains(PyWeakReference *proxy, PyObject *value) { if (!proxy_checkref(proxy)) return -1; return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value); } /* mapping slots */ static Py_ssize_t proxy_length(PyWeakReference *proxy) { if (!proxy_checkref(proxy)) return -1; return PyObject_Length(PyWeakref_GET_OBJECT(proxy)); } WRAP_BINARY(proxy_getitem, PyObject_GetItem) static int proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value) { if (!proxy_checkref(proxy)) return -1; if (value == NULL) return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key); else return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value); } /* iterator slots */ static PyObject * proxy_iter(PyWeakReference *proxy) { if (!proxy_checkref(proxy)) return NULL; return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy)); } static PyObject * proxy_iternext(PyWeakReference *proxy) { if (!proxy_checkref(proxy)) return NULL; return PyIter_Next(PyWeakref_GET_OBJECT(proxy)); } static PyNumberMethods proxy_as_number = { proxy_add, /*nb_add*/ proxy_sub, /*nb_subtract*/ proxy_mul, /*nb_multiply*/ proxy_div, /*nb_divide*/ proxy_mod, /*nb_remainder*/ proxy_divmod, /*nb_divmod*/ proxy_pow, /*nb_power*/ proxy_neg, /*nb_negative*/ proxy_pos, /*nb_positive*/ proxy_abs, /*nb_absolute*/ (inquiry)proxy_nonzero, /*nb_nonzero*/ proxy_invert, /*nb_invert*/ proxy_lshift, /*nb_lshift*/ proxy_rshift, /*nb_rshift*/ proxy_and, /*nb_and*/ proxy_xor, /*nb_xor*/ proxy_or, /*nb_or*/ 0, /*nb_coerce*/ proxy_int, /*nb_int*/ proxy_long, /*nb_long*/ proxy_float, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ proxy_iadd, /*nb_inplace_add*/ proxy_isub, /*nb_inplace_subtract*/ proxy_imul, /*nb_inplace_multiply*/ proxy_idiv, /*nb_inplace_divide*/ proxy_imod, /*nb_inplace_remainder*/ proxy_ipow, /*nb_inplace_power*/ proxy_ilshift, /*nb_inplace_lshift*/ proxy_irshift, /*nb_inplace_rshift*/ proxy_iand, /*nb_inplace_and*/ proxy_ixor, /*nb_inplace_xor*/ proxy_ior, /*nb_inplace_or*/ }; static PySequenceMethods proxy_as_sequence = { (lenfunc)proxy_length, /*sq_length*/ 0, /*sq_concat*/ 0, /*sq_repeat*/ 0, /*sq_item*/ (ssizessizeargfunc)proxy_slice, /*sq_slice*/ 0, /*sq_ass_item*/ (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/ (objobjproc)proxy_contains, /* sq_contains */ }; static PyMappingMethods proxy_as_mapping = { (lenfunc)proxy_length, /*mp_length*/ proxy_getitem, /*mp_subscript*/ (objobjargproc)proxy_setitem, /*mp_ass_subscript*/ }; PyTypeObject _PyWeakref_ProxyType = { PyObject_HEAD_INIT(&PyType_Type) 0, "weakproxy", sizeof(PyWeakReference), 0, /* methods */ (destructor)proxy_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ proxy_compare, /* tp_compare */ (reprfunc)proxy_repr, /* tp_repr */ &proxy_as_number, /* tp_as_number */ &proxy_as_sequence, /* tp_as_sequence */ &proxy_as_mapping, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ proxy_str, /* tp_str */ proxy_getattr, /* tp_getattro */ (setattrofunc)proxy_setattr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ 0, /* tp_doc */ (traverseproc)gc_traverse, /* tp_traverse */ (inquiry)gc_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)proxy_iter, /* tp_iter */ (iternextfunc)proxy_iternext, /* tp_iternext */ }; PyTypeObject _PyWeakref_CallableProxyType = { PyObject_HEAD_INIT(&PyType_Type) 0, "weakcallableproxy", sizeof(PyWeakReference), 0, /* methods */ (destructor)proxy_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ proxy_compare, /* tp_compare */ (unaryfunc)proxy_repr, /* tp_repr */ &proxy_as_number, /* tp_as_number */ &proxy_as_sequence, /* tp_as_sequence */ &proxy_as_mapping, /* tp_as_mapping */ 0, /* tp_hash */ proxy_call, /* tp_call */ proxy_str, /* tp_str */ proxy_getattr, /* tp_getattro */ (setattrofunc)proxy_setattr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ 0, /* tp_doc */ (traverseproc)gc_traverse, /* tp_traverse */ (inquiry)gc_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)proxy_iter, /* tp_iter */ (iternextfunc)proxy_iternext, /* tp_iternext */ }; PyObject * PyWeakref_NewRef(PyObject *ob, PyObject *callback) { PyWeakReference *result = NULL; PyWeakReference **list; PyWeakReference *ref, *proxy; if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) { PyErr_Format(PyExc_TypeError, "cannot create weak reference to '%s' object", ob->ob_type->tp_name); return NULL; } list = GET_WEAKREFS_LISTPTR(ob); get_basic_refs(*list, &ref, &proxy); if (callback == Py_None) callback = NULL; if (callback == NULL) /* return existing weak reference if it exists */ result = ref; if (result != NULL) Py_INCREF(result); else { /* Note: new_weakref() can trigger cyclic GC, so the weakref list on ob can be mutated. This means that the ref and proxy pointers we got back earlier may have been collected, so we need to compute these values again before we use them. */ result = new_weakref(ob, callback); if (result != NULL) { get_basic_refs(*list, &ref, &proxy); if (callback == NULL) { if (ref == NULL) insert_head(result, list); else { /* Someone else added a ref without a callback during GC. Return that one instead of this one to avoid violating the invariants of the list of weakrefs for ob. */ Py_DECREF(result); Py_INCREF(ref); result = ref; } } else { PyWeakReference *prev; prev = (proxy == NULL) ? ref : proxy; if (prev == NULL) insert_head(result, list); else insert_after(result, prev); } } } return (PyObject *) result; } PyObject * PyWeakref_NewProxy(PyObject *ob, PyObject *callback) { PyWeakReference *result = NULL; PyWeakReference **list; PyWeakReference *ref, *proxy; if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) { PyErr_Format(PyExc_TypeError, "cannot create weak reference to '%s' object", ob->ob_type->tp_name); return NULL; } list = GET_WEAKREFS_LISTPTR(ob); get_basic_refs(*list, &ref, &proxy); if (callback == Py_None) callback = NULL; if (callback == NULL) /* attempt to return an existing weak reference if it exists */ result = proxy; if (result != NULL) Py_INCREF(result); else { /* Note: new_weakref() can trigger cyclic GC, so the weakref list on ob can be mutated. This means that the ref and proxy pointers we got back earlier may have been collected, so we need to compute these values again before we use them. */ result = new_weakref(ob, callback); if (result != NULL) { PyWeakReference *prev; if (PyCallable_Check(ob)) result->ob_type = &_PyWeakref_CallableProxyType; else result->ob_type = &_PyWeakref_ProxyType; get_basic_refs(*list, &ref, &proxy); if (callback == NULL) { if (proxy != NULL) { /* Someone else added a proxy without a callback during GC. Return that one instead of this one to avoid violating the invariants of the list of weakrefs for ob. */ Py_DECREF(result); Py_INCREF(result = proxy); goto skip_insert; } prev = ref; } else prev = (proxy == NULL) ? ref : proxy; if (prev == NULL) insert_head(result, list); else insert_after(result, prev); skip_insert: ; } } return (PyObject *) result; } PyObject * PyWeakref_GetObject(PyObject *ref) { if (ref == NULL || !PyWeakref_Check(ref)) { PyErr_BadInternalCall(); return NULL; } return PyWeakref_GET_OBJECT(ref); } /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's * handle_weakrefs(). */ static void handle_callback(PyWeakReference *ref, PyObject *callback) { PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL); if (cbresult == NULL) PyErr_WriteUnraisable(callback); else Py_DECREF(cbresult); } /* This function is called by the tp_dealloc handler to clear weak references. * * This iterates through the weak references for 'object' and calls callbacks * for those references which have one. It returns when all callbacks have * been attempted. */ void PyObject_ClearWeakRefs(PyObject *object) { PyWeakReference **list; if (object == NULL || !PyType_SUPPORTS_WEAKREFS(object->ob_type) || object->ob_refcnt != 0) { PyErr_BadInternalCall(); return; } list = GET_WEAKREFS_LISTPTR(object); /* Remove the callback-less basic and proxy references */ if (*list != NULL && (*list)->wr_callback == NULL) { clear_weakref(*list); if (*list != NULL && (*list)->wr_callback == NULL) clear_weakref(*list); } if (*list != NULL) { PyWeakReference *current = *list; Py_ssize_t count = _PyWeakref_GetWeakrefCount(current); int restore_error = PyErr_Occurred() ? 1 : 0; PyObject *err_type, *err_value, *err_tb; if (restore_error) PyErr_Fetch(&err_type, &err_value, &err_tb); if (count == 1) { PyObject *callback = current->wr_callback; current->wr_callback = NULL; clear_weakref(current); if (callback != NULL) { handle_callback(current, callback); Py_DECREF(callback); } } else { PyObject *tuple; Py_ssize_t i = 0; tuple = PyTuple_New(count * 2); if (tuple == NULL) { if (restore_error) PyErr_Fetch(&err_type, &err_value, &err_tb); return; } for (i = 0; i < count; ++i) { PyWeakReference *next = current->wr_next; Py_INCREF(current); PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current); PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback); current->wr_callback = NULL; clear_weakref(current); current = next; } for (i = 0; i < count; ++i) { PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1); if (callback != NULL) { PyObject *item = PyTuple_GET_ITEM(tuple, i * 2); handle_callback((PyWeakReference *)item, callback); } } Py_DECREF(tuple); } if (restore_error) PyErr_Restore(err_type, err_value, err_tb); } }