- Got rid of newmodule.c
[python/dscho.git] / Objects / weakrefobject.c
blob021670a9936a74b3f1e104c6a15fdd8dd8b1e24d
1 #include "Python.h"
2 #include "structmember.h"
5 #define GET_WEAKREFS_LISTPTR(o) \
6 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
9 long
10 _PyWeakref_GetWeakrefCount(PyWeakReference *head)
12 long count = 0;
14 while (head != NULL) {
15 ++count;
16 head = head->wr_next;
18 return count;
22 static PyWeakReference *
23 new_weakref(PyObject *ob, PyObject *callback)
25 PyWeakReference *result;
27 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
28 if (result) {
29 result->hash = -1;
30 result->wr_object = ob;
31 Py_XINCREF(callback);
32 result->wr_callback = callback;
33 PyObject_GC_Track(result);
35 return result;
39 /* This function clears the passed-in reference and removes it from the
40 * list of weak references for the referent. This is the only code that
41 * removes an item from the doubly-linked list of weak references for an
42 * object; it is also responsible for clearing the callback slot.
44 static void
45 clear_weakref(PyWeakReference *self)
47 PyObject *callback = self->wr_callback;
49 if (PyWeakref_GET_OBJECT(self) != Py_None) {
50 PyWeakReference **list = GET_WEAKREFS_LISTPTR(
51 PyWeakref_GET_OBJECT(self));
53 if (*list == self)
54 *list = self->wr_next;
55 self->wr_object = Py_None;
56 self->wr_callback = NULL;
57 if (self->wr_prev != NULL)
58 self->wr_prev->wr_next = self->wr_next;
59 if (self->wr_next != NULL)
60 self->wr_next->wr_prev = self->wr_prev;
61 self->wr_prev = NULL;
62 self->wr_next = NULL;
63 Py_XDECREF(callback);
68 static void
69 weakref_dealloc(PyWeakReference *self)
71 PyObject_GC_UnTrack((PyObject *)self);
72 clear_weakref(self);
73 PyObject_GC_Del(self);
77 static int
78 gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
80 if (self->wr_callback != NULL)
81 return visit(self->wr_callback, arg);
82 return 0;
86 static int
87 gc_clear(PyWeakReference *self)
89 clear_weakref(self);
90 return 0;
94 static PyObject *
95 weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
97 static char *argnames[] = {NULL};
99 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", argnames)) {
100 PyObject *object = PyWeakref_GET_OBJECT(self);
101 Py_INCREF(object);
102 return (object);
104 return NULL;
108 static long
109 weakref_hash(PyWeakReference *self)
111 if (self->hash != -1)
112 return self->hash;
113 if (PyWeakref_GET_OBJECT(self) == Py_None) {
114 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
115 return -1;
117 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
118 return self->hash;
122 static PyObject *
123 weakref_repr(PyWeakReference *self)
125 char buffer[256];
126 if (PyWeakref_GET_OBJECT(self) == Py_None) {
127 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %lx; dead>",
128 (long)(self));
130 else {
131 PyOS_snprintf(buffer, sizeof(buffer),
132 "<weakref at %#lx; to '%.50s' at %#lx>",
133 (long)(self),
134 PyWeakref_GET_OBJECT(self)->ob_type->tp_name,
135 (long)(PyWeakref_GET_OBJECT(self)));
137 return PyString_FromString(buffer);
140 /* Weak references only support equality, not ordering. Two weak references
141 are equal if the underlying objects are equal. If the underlying object has
142 gone away, they are equal if they are identical. */
144 static PyObject *
145 weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
147 if (op != Py_EQ || self->ob_type != other->ob_type) {
148 Py_INCREF(Py_NotImplemented);
149 return Py_NotImplemented;
151 if (PyWeakref_GET_OBJECT(self) == Py_None
152 || PyWeakref_GET_OBJECT(other) == Py_None) {
153 PyObject *res = self==other ? Py_True : Py_False;
154 Py_INCREF(res);
155 return res;
157 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
158 PyWeakref_GET_OBJECT(other), op);
162 PyTypeObject
163 _PyWeakref_RefType = {
164 PyObject_HEAD_INIT(&PyType_Type)
166 "weakref",
167 sizeof(PyWeakReference),
169 (destructor)weakref_dealloc,/*tp_dealloc*/
170 0, /*tp_print*/
171 0, /*tp_getattr*/
172 0, /*tp_setattr*/
173 0, /*tp_compare*/
174 (reprfunc)weakref_repr, /*tp_repr*/
175 0, /*tp_as_number*/
176 0, /*tp_as_sequence*/
177 0, /*tp_as_mapping*/
178 (hashfunc)weakref_hash, /*tp_hash*/
179 (ternaryfunc)weakref_call, /*tp_call*/
180 0, /*tp_str*/
181 0, /*tp_getattro*/
182 0, /*tp_setattro*/
183 0, /*tp_as_buffer*/
184 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE,
185 0, /*tp_doc*/
186 (traverseproc)gc_traverse, /*tp_traverse*/
187 (inquiry)gc_clear, /*tp_clear*/
188 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
189 0, /*tp_weaklistoffset*/
193 static int
194 proxy_checkref(PyWeakReference *proxy)
196 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
197 PyErr_SetString(PyExc_ReferenceError,
198 "weakly-referenced object no longer exists");
199 return 0;
201 return 1;
205 /* If a parameter is a proxy, check that it is still "live" and wrap it,
206 * replacing the original value with the raw object. Raises ReferenceError
207 * if the param is a dead proxy.
209 #define UNWRAP(o) \
210 if (PyWeakref_CheckProxy(o)) { \
211 if (!proxy_checkref((PyWeakReference *)o)) \
212 return NULL; \
213 o = PyWeakref_GET_OBJECT(o); \
216 #define UNWRAP_I(o) \
217 if (PyWeakref_CheckProxy(o)) { \
218 if (!proxy_checkref((PyWeakReference *)o)) \
219 return -1; \
220 o = PyWeakref_GET_OBJECT(o); \
223 #define WRAP_UNARY(method, generic) \
224 static PyObject * \
225 method(PyObject *proxy) { \
226 UNWRAP(proxy); \
227 return generic(proxy); \
230 #define WRAP_BINARY(method, generic) \
231 static PyObject * \
232 method(PyObject *x, PyObject *y) { \
233 UNWRAP(x); \
234 UNWRAP(y); \
235 return generic(x, y); \
238 /* Note that the third arg needs to be checked for NULL since the tp_call
239 * slot can receive NULL for this arg.
241 #define WRAP_TERNARY(method, generic) \
242 static PyObject * \
243 method(PyObject *proxy, PyObject *v, PyObject *w) { \
244 UNWRAP(proxy); \
245 UNWRAP(v); \
246 if (w != NULL) \
247 UNWRAP(w); \
248 return generic(proxy, v, w); \
252 /* direct slots */
254 WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
255 WRAP_UNARY(proxy_str, PyObject_Str)
256 WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
258 static int
259 proxy_print(PyWeakReference *proxy, FILE *fp, int flags)
261 if (!proxy_checkref(proxy))
262 return -1;
263 return PyObject_Print(PyWeakref_GET_OBJECT(proxy), fp, flags);
266 static PyObject *
267 proxy_repr(PyWeakReference *proxy)
269 char buf[160];
270 PyOS_snprintf(buf, sizeof(buf),
271 "<weakref at %p to %.100s at %p>", proxy,
272 PyWeakref_GET_OBJECT(proxy)->ob_type->tp_name,
273 PyWeakref_GET_OBJECT(proxy));
274 return PyString_FromString(buf);
278 static int
279 proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
281 if (!proxy_checkref(proxy))
282 return -1;
283 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
286 static int
287 proxy_compare(PyObject *proxy, PyObject *v)
289 UNWRAP_I(proxy);
290 UNWRAP_I(v);
291 return PyObject_Compare(proxy, v);
294 /* number slots */
295 WRAP_BINARY(proxy_add, PyNumber_Add)
296 WRAP_BINARY(proxy_sub, PyNumber_Subtract)
297 WRAP_BINARY(proxy_mul, PyNumber_Multiply)
298 WRAP_BINARY(proxy_div, PyNumber_Divide)
299 WRAP_BINARY(proxy_mod, PyNumber_Remainder)
300 WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
301 WRAP_TERNARY(proxy_pow, PyNumber_Power)
302 WRAP_UNARY(proxy_neg, PyNumber_Negative)
303 WRAP_UNARY(proxy_pos, PyNumber_Positive)
304 WRAP_UNARY(proxy_abs, PyNumber_Absolute)
305 WRAP_UNARY(proxy_invert, PyNumber_Invert)
306 WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
307 WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
308 WRAP_BINARY(proxy_and, PyNumber_And)
309 WRAP_BINARY(proxy_xor, PyNumber_Xor)
310 WRAP_BINARY(proxy_or, PyNumber_Or)
311 WRAP_UNARY(proxy_int, PyNumber_Int)
312 WRAP_UNARY(proxy_long, PyNumber_Long)
313 WRAP_UNARY(proxy_float, PyNumber_Float)
314 WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
315 WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
316 WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
317 WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
318 WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
319 WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
320 WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
321 WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
322 WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
323 WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
324 WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
326 static int
327 proxy_nonzero(PyWeakReference *proxy)
329 PyObject *o = PyWeakref_GET_OBJECT(proxy);
330 if (!proxy_checkref(proxy))
331 return 1;
332 if (o->ob_type->tp_as_number &&
333 o->ob_type->tp_as_number->nb_nonzero)
334 return (*o->ob_type->tp_as_number->nb_nonzero)(o);
335 else
336 return 1;
339 /* sequence slots */
341 static PyObject *
342 proxy_slice(PyWeakReference *proxy, int i, int j)
344 if (!proxy_checkref(proxy))
345 return NULL;
346 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
349 static int
350 proxy_ass_slice(PyWeakReference *proxy, int i, int j, PyObject *value)
352 if (!proxy_checkref(proxy))
353 return -1;
354 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
357 static int
358 proxy_contains(PyWeakReference *proxy, PyObject *value)
360 if (!proxy_checkref(proxy))
361 return -1;
362 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
366 /* mapping slots */
368 static int
369 proxy_length(PyWeakReference *proxy)
371 if (!proxy_checkref(proxy))
372 return -1;
373 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
376 WRAP_BINARY(proxy_getitem, PyObject_GetItem)
378 static int
379 proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
381 if (!proxy_checkref(proxy))
382 return -1;
383 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
387 static PyNumberMethods proxy_as_number = {
388 (binaryfunc)proxy_add, /*nb_add*/
389 (binaryfunc)proxy_sub, /*nb_subtract*/
390 (binaryfunc)proxy_mul, /*nb_multiply*/
391 (binaryfunc)proxy_div, /*nb_divide*/
392 (binaryfunc)proxy_mod, /*nb_remainder*/
393 (binaryfunc)proxy_divmod, /*nb_divmod*/
394 (ternaryfunc)proxy_pow, /*nb_power*/
395 (unaryfunc)proxy_neg, /*nb_negative*/
396 (unaryfunc)proxy_pos, /*nb_positive*/
397 (unaryfunc)proxy_abs, /*nb_absolute*/
398 (inquiry)proxy_nonzero, /*nb_nonzero*/
399 (unaryfunc)proxy_invert, /*nb_invert*/
400 (binaryfunc)proxy_lshift, /*nb_lshift*/
401 (binaryfunc)proxy_rshift, /*nb_rshift*/
402 (binaryfunc)proxy_and, /*nb_and*/
403 (binaryfunc)proxy_xor, /*nb_xor*/
404 (binaryfunc)proxy_or, /*nb_or*/
405 (coercion)0, /*nb_coerce*/
406 (unaryfunc)proxy_int, /*nb_int*/
407 (unaryfunc)proxy_long, /*nb_long*/
408 (unaryfunc)proxy_float, /*nb_float*/
409 (unaryfunc)0, /*nb_oct*/
410 (unaryfunc)0, /*nb_hex*/
411 (binaryfunc)proxy_iadd, /*nb_inplace_add*/
412 (binaryfunc)proxy_isub, /*nb_inplace_subtract*/
413 (binaryfunc)proxy_imul, /*nb_inplace_multiply*/
414 (binaryfunc)proxy_idiv, /*nb_inplace_divide*/
415 (binaryfunc)proxy_imod, /*nb_inplace_remainder*/
416 (ternaryfunc)proxy_ipow, /*nb_inplace_power*/
417 (binaryfunc)proxy_ilshift, /*nb_inplace_lshift*/
418 (binaryfunc)proxy_irshift, /*nb_inplace_rshift*/
419 (binaryfunc)proxy_iand, /*nb_inplace_and*/
420 (binaryfunc)proxy_ixor, /*nb_inplace_xor*/
421 (binaryfunc)proxy_ior, /*nb_inplace_or*/
424 static PySequenceMethods proxy_as_sequence = {
425 (inquiry)proxy_length, /*sq_length*/
426 0, /*sq_concat*/
427 0, /*sq_repeat*/
428 0, /*sq_item*/
429 (intintargfunc)proxy_slice, /*sq_slice*/
430 0, /*sq_ass_item*/
431 (intintobjargproc)proxy_ass_slice, /*sq_ass_slice*/
432 (objobjproc)proxy_contains, /* sq_contains */
435 static PyMappingMethods proxy_as_mapping = {
436 (inquiry)proxy_length, /*mp_length*/
437 (binaryfunc)proxy_getitem, /*mp_subscript*/
438 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
442 PyTypeObject
443 _PyWeakref_ProxyType = {
444 PyObject_HEAD_INIT(&PyType_Type)
446 "weakproxy",
447 sizeof(PyWeakReference),
449 /* methods */
450 (destructor)weakref_dealloc,/*tp_dealloc*/
451 (printfunc)proxy_print, /*tp_print*/
452 0, /*tp_getattr*/
453 0, /*tp_setattr*/
454 proxy_compare, /*tp_compare*/
455 (unaryfunc)proxy_repr, /*tp_repr*/
456 &proxy_as_number, /*tp_as_number*/
457 &proxy_as_sequence, /*tp_as_sequence*/
458 &proxy_as_mapping, /*tp_as_mapping*/
459 0, /*tp_hash*/
460 (ternaryfunc)0, /*tp_call*/
461 (unaryfunc)proxy_str, /*tp_str*/
462 (getattrofunc)proxy_getattr,/*tp_getattro*/
463 (setattrofunc)proxy_setattr,/*tp_setattro*/
464 0, /*tp_as_buffer*/
465 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
466 |Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
467 0, /*tp_doc*/
468 (traverseproc)gc_traverse, /*tp_traverse*/
469 (inquiry)gc_clear, /*tp_clear*/
473 PyTypeObject
474 _PyWeakref_CallableProxyType = {
475 PyObject_HEAD_INIT(&PyType_Type)
477 "weakcallableproxy",
478 sizeof(PyWeakReference),
480 /* methods */
481 (destructor)weakref_dealloc,/*tp_dealloc*/
482 (printfunc)proxy_print, /*tp_print*/
483 0, /*tp_getattr*/
484 0, /*tp_setattr*/
485 proxy_compare, /*tp_compare*/
486 (unaryfunc)proxy_repr, /*tp_repr*/
487 &proxy_as_number, /*tp_as_number*/
488 &proxy_as_sequence, /*tp_as_sequence*/
489 &proxy_as_mapping, /*tp_as_mapping*/
490 0, /*tp_hash*/
491 (ternaryfunc)proxy_call, /*tp_call*/
492 (unaryfunc)proxy_str, /*tp_str*/
493 (getattrofunc)proxy_getattr,/*tp_getattro*/
494 (setattrofunc)proxy_setattr,/*tp_setattro*/
495 0, /*tp_as_buffer*/
496 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
497 |Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
498 0, /*tp_doc*/
499 (traverseproc)gc_traverse, /*tp_traverse*/
500 (inquiry)gc_clear, /*tp_clear*/
504 /* Given the head of an object's list of weak references, extract the
505 * two callback-less refs (ref and proxy). Used to determine if the
506 * shared references exist and to determine the back link for newly
507 * inserted references.
509 static void
510 get_basic_refs(PyWeakReference *head,
511 PyWeakReference **refp, PyWeakReference **proxyp)
513 *refp = NULL;
514 *proxyp = NULL;
516 if (head != NULL && head->wr_callback == NULL) {
517 if (head->ob_type == &_PyWeakref_RefType) {
518 *refp = head;
519 head = head->wr_next;
521 if (head != NULL && head->wr_callback == NULL) {
522 *proxyp = head;
523 head = head->wr_next;
528 /* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
529 static void
530 insert_after(PyWeakReference *newref, PyWeakReference *prev)
532 newref->wr_prev = prev;
533 newref->wr_next = prev->wr_next;
534 if (prev->wr_next != NULL)
535 prev->wr_next->wr_prev = newref;
536 prev->wr_next = newref;
539 /* Insert 'newref' at the head of the list; 'list' points to the variable
540 * that stores the head.
542 static void
543 insert_head(PyWeakReference *newref, PyWeakReference **list)
545 PyWeakReference *next = *list;
547 newref->wr_prev = NULL;
548 newref->wr_next = next;
549 if (next != NULL)
550 next->wr_prev = newref;
551 *list = newref;
555 PyObject *
556 PyWeakref_NewRef(PyObject *ob, PyObject *callback)
558 PyWeakReference *result = NULL;
559 PyWeakReference **list;
560 PyWeakReference *ref, *proxy;
562 if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) {
563 PyErr_Format(PyExc_TypeError,
564 "cannot create weak reference to '%s' object",
565 ob->ob_type->tp_name);
566 return NULL;
568 list = GET_WEAKREFS_LISTPTR(ob);
569 get_basic_refs(*list, &ref, &proxy);
570 if (callback == NULL || callback == Py_None)
571 /* return existing weak reference if it exists */
572 result = ref;
573 if (result != NULL)
574 Py_XINCREF(result);
575 else {
576 result = new_weakref(ob, callback);
577 if (result != NULL) {
578 if (callback == NULL) {
579 insert_head(result, list);
581 else {
582 PyWeakReference *prev = (proxy == NULL) ? ref : proxy;
584 if (prev == NULL)
585 insert_head(result, list);
586 else
587 insert_after(result, prev);
591 return (PyObject *) result;
595 PyObject *
596 PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
598 PyWeakReference *result = NULL;
599 PyWeakReference **list;
600 PyWeakReference *ref, *proxy;
602 if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) {
603 PyErr_Format(PyExc_TypeError,
604 "cannot create weak reference to '%s' object",
605 ob->ob_type->tp_name);
606 return NULL;
608 list = GET_WEAKREFS_LISTPTR(ob);
609 get_basic_refs(*list, &ref, &proxy);
610 if (callback == NULL)
611 /* attempt to return an existing weak reference if it exists */
612 result = proxy;
613 if (result != NULL)
614 Py_XINCREF(result);
615 else {
616 result = new_weakref(ob, callback);
617 if (result != NULL) {
618 PyWeakReference *prev;
620 if (PyCallable_Check(ob))
621 result->ob_type = &_PyWeakref_CallableProxyType;
622 else
623 result->ob_type = &_PyWeakref_ProxyType;
624 if (callback == NULL)
625 prev = ref;
626 else
627 prev = (proxy == NULL) ? ref : proxy;
629 if (prev == NULL)
630 insert_head(result, list);
631 else
632 insert_after(result, prev);
635 return (PyObject *) result;
639 PyObject *
640 PyWeakref_GetObject(PyObject *ref)
642 if (ref == NULL || !PyWeakref_Check(ref)) {
643 PyErr_BadInternalCall();
644 return NULL;
646 return PyWeakref_GET_OBJECT(ref);
650 static void
651 handle_callback(PyWeakReference *ref, PyObject *callback)
653 PyObject *cbresult = PyObject_CallFunction(callback, "O", ref);
655 if (cbresult == NULL)
656 PyErr_WriteUnraisable(callback);
657 else
658 Py_DECREF(cbresult);
661 /* This function is called by the tp_dealloc handler to clear weak references.
663 * This iterates through the weak references for 'object' and calls callbacks
664 * for those references which have one. It returns when all callbacks have
665 * been attempted.
667 void
668 PyObject_ClearWeakRefs(PyObject *object)
670 PyWeakReference **list;
672 if (object == NULL
673 || !PyType_SUPPORTS_WEAKREFS(object->ob_type)
674 || object->ob_refcnt != 0) {
675 PyErr_BadInternalCall();
676 return;
678 list = GET_WEAKREFS_LISTPTR(object);
679 /* Remove the callback-less basic and proxy references */
680 if (*list != NULL && (*list)->wr_callback == NULL) {
681 clear_weakref(*list);
682 if (*list != NULL && (*list)->wr_callback == NULL)
683 clear_weakref(*list);
685 if (*list != NULL) {
686 PyWeakReference *current = *list;
687 int count = _PyWeakref_GetWeakrefCount(current);
688 int restore_error = PyErr_Occurred() ? 1 : 0;
689 PyObject *err_type, *err_value, *err_tb;
691 if (restore_error)
692 PyErr_Fetch(&err_type, &err_value, &err_tb);
693 if (count == 1) {
694 PyObject *callback = current->wr_callback;
696 current->wr_callback = NULL;
697 clear_weakref(current);
698 handle_callback(current, callback);
699 Py_DECREF(callback);
701 else {
702 PyObject *tuple = PyTuple_New(count * 2);
703 int i = 0;
705 for (i = 0; i < count; ++i) {
706 PyWeakReference *next = current->wr_next;
708 Py_INCREF(current);
709 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
710 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
711 current->wr_callback = NULL;
712 clear_weakref(current);
713 current = next;
715 for (i = 0; i < count; ++i) {
716 PyObject *current = PyTuple_GET_ITEM(tuple, i * 2);
717 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
719 handle_callback((PyWeakReference *)current, callback);
721 Py_DECREF(tuple);
723 if (restore_error)
724 PyErr_Restore(err_type, err_value, err_tb);