This commit was manufactured by cvs2svn to create tag
[python/dscho.git] / Objects / weakrefobject.c
blob2e02cf27cabc4793703a732e881a2626689dfc30
1 #include "Python.h"
2 #include "structmember.h"
5 #define GET_WEAKREFS_LISTPTR(o) \
6 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
8 static PyWeakReference *
9 free_list = NULL;
12 long
13 _PyWeakref_GetWeakrefCount(PyWeakReference *head)
15 long count = 0;
17 while (head != NULL) {
18 ++count;
19 head = head->wr_next;
21 return count;
25 static PyWeakReference *
26 new_weakref(void)
28 PyWeakReference *result;
30 if (free_list != NULL) {
31 result = free_list;
32 free_list = result->wr_next;
33 result->ob_type = &_PyWeakref_RefType;
34 _Py_NewReference((PyObject *)result);
36 else {
37 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
39 if (result)
40 result->hash = -1;
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 *list = self->wr_next;
61 self->wr_object = Py_None;
62 self->wr_callback = NULL;
63 if (self->wr_prev != NULL)
64 self->wr_prev->wr_next = self->wr_next;
65 if (self->wr_next != NULL)
66 self->wr_next->wr_prev = self->wr_prev;
67 self->wr_prev = NULL;
68 self->wr_next = NULL;
69 Py_XDECREF(callback);
74 static void
75 weakref_dealloc(PyWeakReference *self)
77 PyObject_GC_UnTrack((PyObject *)self);
78 clear_weakref(self);
79 self->wr_next = free_list;
80 free_list = self;
84 static int
85 gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
87 if (self->wr_callback != NULL)
88 return visit(self->wr_callback, arg);
89 return 0;
93 static int
94 gc_clear(PyWeakReference *self)
96 clear_weakref(self);
97 return 0;
101 static PyObject *
102 weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
104 static char *argnames[] = {NULL};
106 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", argnames)) {
107 PyObject *object = PyWeakref_GET_OBJECT(self);
108 Py_INCREF(object);
109 return (object);
111 return NULL;
115 static long
116 weakref_hash(PyWeakReference *self)
118 if (self->hash != -1)
119 return self->hash;
120 if (PyWeakref_GET_OBJECT(self) == Py_None) {
121 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
122 return -1;
124 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
125 return self->hash;
129 static PyObject *
130 weakref_repr(PyWeakReference *self)
132 char buffer[256];
133 if (PyWeakref_GET_OBJECT(self) == Py_None) {
134 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %lx; dead>",
135 (long)(self));
137 else {
138 PyOS_snprintf(buffer, sizeof(buffer),
139 "<weakref at %#lx; to '%.50s' at %#lx>",
140 (long)(self),
141 PyWeakref_GET_OBJECT(self)->ob_type->tp_name,
142 (long)(PyWeakref_GET_OBJECT(self)));
144 return PyString_FromString(buffer);
147 /* Weak references only support equality, not ordering. Two weak references
148 are equal if the underlying objects are equal. If the underlying object has
149 gone away, they are equal if they are identical. */
151 static PyObject *
152 weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
154 if (op != Py_EQ || self->ob_type != other->ob_type) {
155 Py_INCREF(Py_NotImplemented);
156 return Py_NotImplemented;
158 if (PyWeakref_GET_OBJECT(self) == Py_None
159 || PyWeakref_GET_OBJECT(other) == Py_None) {
160 PyObject *res = self==other ? Py_True : Py_False;
161 Py_INCREF(res);
162 return res;
164 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
165 PyWeakref_GET_OBJECT(other), op);
169 PyTypeObject
170 _PyWeakref_RefType = {
171 PyObject_HEAD_INIT(&PyType_Type)
173 "weakref",
174 sizeof(PyWeakReference),
176 (destructor)weakref_dealloc,/*tp_dealloc*/
177 0, /*tp_print*/
178 0, /*tp_getattr*/
179 0, /*tp_setattr*/
180 0, /*tp_compare*/
181 (reprfunc)weakref_repr, /*tp_repr*/
182 0, /*tp_as_number*/
183 0, /*tp_as_sequence*/
184 0, /*tp_as_mapping*/
185 (hashfunc)weakref_hash, /*tp_hash*/
186 (ternaryfunc)weakref_call, /*tp_call*/
187 0, /*tp_str*/
188 0, /*tp_getattro*/
189 0, /*tp_setattro*/
190 0, /*tp_as_buffer*/
191 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE,
192 0, /*tp_doc*/
193 (traverseproc)gc_traverse, /*tp_traverse*/
194 (inquiry)gc_clear, /*tp_clear*/
195 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
196 0, /*tp_weaklistoffset*/
200 static int
201 proxy_checkref(PyWeakReference *proxy)
203 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
204 PyErr_SetString(PyExc_ReferenceError,
205 "weakly-referenced object no longer exists");
206 return 0;
208 return 1;
212 /* If a parameter is a proxy, check that it is still "live" and wrap it,
213 * replacing the original value with the raw object. Raises ReferenceError
214 * if the param is a dead proxy.
216 #define UNWRAP(o) \
217 if (PyWeakref_CheckProxy(o)) { \
218 if (!proxy_checkref((PyWeakReference *)o)) \
219 return NULL; \
220 o = PyWeakref_GET_OBJECT(o); \
223 #define UNWRAP_I(o) \
224 if (PyWeakref_CheckProxy(o)) { \
225 if (!proxy_checkref((PyWeakReference *)o)) \
226 return -1; \
227 o = PyWeakref_GET_OBJECT(o); \
230 #define WRAP_UNARY(method, generic) \
231 static PyObject * \
232 method(PyObject *proxy) { \
233 UNWRAP(proxy); \
234 return generic(proxy); \
237 #define WRAP_BINARY(method, generic) \
238 static PyObject * \
239 method(PyObject *x, PyObject *y) { \
240 UNWRAP(x); \
241 UNWRAP(y); \
242 return generic(x, y); \
245 /* Note that the third arg needs to be checked for NULL since the tp_call
246 * slot can receive NULL for this arg.
248 #define WRAP_TERNARY(method, generic) \
249 static PyObject * \
250 method(PyObject *proxy, PyObject *v, PyObject *w) { \
251 UNWRAP(proxy); \
252 UNWRAP(v); \
253 if (w != NULL) \
254 UNWRAP(w); \
255 return generic(proxy, v, w); \
259 /* direct slots */
261 WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
262 WRAP_UNARY(proxy_str, PyObject_Str)
263 WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
265 static int
266 proxy_print(PyWeakReference *proxy, FILE *fp, int flags)
268 if (!proxy_checkref(proxy))
269 return -1;
270 return PyObject_Print(PyWeakref_GET_OBJECT(proxy), fp, flags);
273 static PyObject *
274 proxy_repr(PyWeakReference *proxy)
276 char buf[160];
277 PyOS_snprintf(buf, sizeof(buf),
278 "<weakref at %p to %.100s at %p>", proxy,
279 PyWeakref_GET_OBJECT(proxy)->ob_type->tp_name,
280 PyWeakref_GET_OBJECT(proxy));
281 return PyString_FromString(buf);
285 static int
286 proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
288 if (!proxy_checkref(proxy))
289 return -1;
290 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
293 static int
294 proxy_compare(PyObject *proxy, PyObject *v)
296 UNWRAP_I(proxy);
297 UNWRAP_I(v);
298 return PyObject_Compare(proxy, v);
301 /* number slots */
302 WRAP_BINARY(proxy_add, PyNumber_Add)
303 WRAP_BINARY(proxy_sub, PyNumber_Subtract)
304 WRAP_BINARY(proxy_mul, PyNumber_Multiply)
305 WRAP_BINARY(proxy_div, PyNumber_Divide)
306 WRAP_BINARY(proxy_mod, PyNumber_Remainder)
307 WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
308 WRAP_TERNARY(proxy_pow, PyNumber_Power)
309 WRAP_UNARY(proxy_neg, PyNumber_Negative)
310 WRAP_UNARY(proxy_pos, PyNumber_Positive)
311 WRAP_UNARY(proxy_abs, PyNumber_Absolute)
312 WRAP_UNARY(proxy_invert, PyNumber_Invert)
313 WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
314 WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
315 WRAP_BINARY(proxy_and, PyNumber_And)
316 WRAP_BINARY(proxy_xor, PyNumber_Xor)
317 WRAP_BINARY(proxy_or, PyNumber_Or)
318 WRAP_UNARY(proxy_int, PyNumber_Int)
319 WRAP_UNARY(proxy_long, PyNumber_Long)
320 WRAP_UNARY(proxy_float, PyNumber_Float)
321 WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
322 WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
323 WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
324 WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
325 WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
326 WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
327 WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
328 WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
329 WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
330 WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
331 WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
333 static int
334 proxy_nonzero(PyWeakReference *proxy)
336 PyObject *o = PyWeakref_GET_OBJECT(proxy);
337 if (!proxy_checkref(proxy))
338 return 1;
339 if (o->ob_type->tp_as_number &&
340 o->ob_type->tp_as_number->nb_nonzero)
341 return (*o->ob_type->tp_as_number->nb_nonzero)(o);
342 else
343 return 1;
346 /* sequence slots */
348 static PyObject *
349 proxy_slice(PyWeakReference *proxy, int i, int j)
351 if (!proxy_checkref(proxy))
352 return NULL;
353 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
356 static int
357 proxy_ass_slice(PyWeakReference *proxy, int i, int j, PyObject *value)
359 if (!proxy_checkref(proxy))
360 return -1;
361 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
364 static int
365 proxy_contains(PyWeakReference *proxy, PyObject *value)
367 if (!proxy_checkref(proxy))
368 return -1;
369 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
373 /* mapping slots */
375 static int
376 proxy_length(PyWeakReference *proxy)
378 if (!proxy_checkref(proxy))
379 return -1;
380 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
383 WRAP_BINARY(proxy_getitem, PyObject_GetItem)
385 static int
386 proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
388 if (!proxy_checkref(proxy))
389 return -1;
390 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
394 static PyNumberMethods proxy_as_number = {
395 (binaryfunc)proxy_add, /*nb_add*/
396 (binaryfunc)proxy_sub, /*nb_subtract*/
397 (binaryfunc)proxy_mul, /*nb_multiply*/
398 (binaryfunc)proxy_div, /*nb_divide*/
399 (binaryfunc)proxy_mod, /*nb_remainder*/
400 (binaryfunc)proxy_divmod, /*nb_divmod*/
401 (ternaryfunc)proxy_pow, /*nb_power*/
402 (unaryfunc)proxy_neg, /*nb_negative*/
403 (unaryfunc)proxy_pos, /*nb_positive*/
404 (unaryfunc)proxy_abs, /*nb_absolute*/
405 (inquiry)proxy_nonzero, /*nb_nonzero*/
406 (unaryfunc)proxy_invert, /*nb_invert*/
407 (binaryfunc)proxy_lshift, /*nb_lshift*/
408 (binaryfunc)proxy_rshift, /*nb_rshift*/
409 (binaryfunc)proxy_and, /*nb_and*/
410 (binaryfunc)proxy_xor, /*nb_xor*/
411 (binaryfunc)proxy_or, /*nb_or*/
412 (coercion)0, /*nb_coerce*/
413 (unaryfunc)proxy_int, /*nb_int*/
414 (unaryfunc)proxy_long, /*nb_long*/
415 (unaryfunc)proxy_float, /*nb_float*/
416 (unaryfunc)0, /*nb_oct*/
417 (unaryfunc)0, /*nb_hex*/
418 (binaryfunc)proxy_iadd, /*nb_inplace_add*/
419 (binaryfunc)proxy_isub, /*nb_inplace_subtract*/
420 (binaryfunc)proxy_imul, /*nb_inplace_multiply*/
421 (binaryfunc)proxy_idiv, /*nb_inplace_divide*/
422 (binaryfunc)proxy_imod, /*nb_inplace_remainder*/
423 (ternaryfunc)proxy_ipow, /*nb_inplace_power*/
424 (binaryfunc)proxy_ilshift, /*nb_inplace_lshift*/
425 (binaryfunc)proxy_irshift, /*nb_inplace_rshift*/
426 (binaryfunc)proxy_iand, /*nb_inplace_and*/
427 (binaryfunc)proxy_ixor, /*nb_inplace_xor*/
428 (binaryfunc)proxy_ior, /*nb_inplace_or*/
431 static PySequenceMethods proxy_as_sequence = {
432 (inquiry)proxy_length, /*sq_length*/
433 0, /*sq_concat*/
434 0, /*sq_repeat*/
435 0, /*sq_item*/
436 (intintargfunc)proxy_slice, /*sq_slice*/
437 0, /*sq_ass_item*/
438 (intintobjargproc)proxy_ass_slice, /*sq_ass_slice*/
439 (objobjproc)proxy_contains, /* sq_contains */
442 static PyMappingMethods proxy_as_mapping = {
443 (inquiry)proxy_length, /*mp_length*/
444 (binaryfunc)proxy_getitem, /*mp_subscript*/
445 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
449 PyTypeObject
450 _PyWeakref_ProxyType = {
451 PyObject_HEAD_INIT(&PyType_Type)
453 "weakproxy",
454 sizeof(PyWeakReference),
456 /* methods */
457 (destructor)weakref_dealloc,/*tp_dealloc*/
458 (printfunc)proxy_print, /*tp_print*/
459 0, /*tp_getattr*/
460 0, /*tp_setattr*/
461 proxy_compare, /*tp_compare*/
462 (unaryfunc)proxy_repr, /*tp_repr*/
463 &proxy_as_number, /*tp_as_number*/
464 &proxy_as_sequence, /*tp_as_sequence*/
465 &proxy_as_mapping, /*tp_as_mapping*/
466 0, /*tp_hash*/
467 (ternaryfunc)0, /*tp_call*/
468 (unaryfunc)proxy_str, /*tp_str*/
469 (getattrofunc)proxy_getattr,/*tp_getattro*/
470 (setattrofunc)proxy_setattr,/*tp_setattro*/
471 0, /*tp_as_buffer*/
472 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
473 |Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
474 0, /*tp_doc*/
475 (traverseproc)gc_traverse, /*tp_traverse*/
476 (inquiry)gc_clear, /*tp_clear*/
480 PyTypeObject
481 _PyWeakref_CallableProxyType = {
482 PyObject_HEAD_INIT(&PyType_Type)
484 "weakcallableproxy",
485 sizeof(PyWeakReference),
487 /* methods */
488 (destructor)weakref_dealloc,/*tp_dealloc*/
489 (printfunc)proxy_print, /*tp_print*/
490 0, /*tp_getattr*/
491 0, /*tp_setattr*/
492 proxy_compare, /*tp_compare*/
493 (unaryfunc)proxy_repr, /*tp_repr*/
494 &proxy_as_number, /*tp_as_number*/
495 &proxy_as_sequence, /*tp_as_sequence*/
496 &proxy_as_mapping, /*tp_as_mapping*/
497 0, /*tp_hash*/
498 (ternaryfunc)proxy_call, /*tp_call*/
499 (unaryfunc)proxy_str, /*tp_str*/
500 (getattrofunc)proxy_getattr,/*tp_getattro*/
501 (setattrofunc)proxy_setattr,/*tp_setattro*/
502 0, /*tp_as_buffer*/
503 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
504 |Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
505 0, /*tp_doc*/
506 (traverseproc)gc_traverse, /*tp_traverse*/
507 (inquiry)gc_clear, /*tp_clear*/
511 /* Given the head of an object's list of weak references, extract the
512 * two callback-less refs (ref and proxy). Used to determine if the
513 * shared references exist and to determine the back link for newly
514 * inserted references.
516 static void
517 get_basic_refs(PyWeakReference *head,
518 PyWeakReference **refp, PyWeakReference **proxyp)
520 *refp = NULL;
521 *proxyp = NULL;
523 if (head != NULL && head->wr_callback == NULL) {
524 if (head->ob_type == &_PyWeakref_RefType) {
525 *refp = head;
526 head = head->wr_next;
528 if (head != NULL && head->wr_callback == NULL) {
529 *proxyp = head;
530 head = head->wr_next;
535 /* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
536 static void
537 insert_after(PyWeakReference *newref, PyWeakReference *prev)
539 newref->wr_prev = prev;
540 newref->wr_next = prev->wr_next;
541 if (prev->wr_next != NULL)
542 prev->wr_next->wr_prev = newref;
543 prev->wr_next = newref;
546 /* Insert 'newref' at the head of the list; 'list' points to the variable
547 * that stores the head.
549 static void
550 insert_head(PyWeakReference *newref, PyWeakReference **list)
552 PyWeakReference *next = *list;
554 newref->wr_prev = NULL;
555 newref->wr_next = next;
556 if (next != NULL)
557 next->wr_prev = newref;
558 *list = newref;
562 PyObject *
563 PyWeakref_NewRef(PyObject *ob, PyObject *callback)
565 PyWeakReference *result = NULL;
566 PyWeakReference **list;
567 PyWeakReference *ref, *proxy;
569 if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) {
570 PyErr_Format(PyExc_TypeError,
571 "cannot create weak reference to '%s' object",
572 ob->ob_type->tp_name);
573 return NULL;
575 list = GET_WEAKREFS_LISTPTR(ob);
576 get_basic_refs(*list, &ref, &proxy);
577 if (callback == NULL || callback == Py_None)
578 /* return existing weak reference if it exists */
579 result = ref;
580 if (result != NULL)
581 Py_XINCREF(result);
582 else {
583 result = new_weakref();
584 if (result != NULL) {
585 Py_XINCREF(callback);
586 result->wr_callback = callback;
587 result->wr_object = ob;
588 if (callback == NULL) {
589 insert_head(result, list);
591 else {
592 PyWeakReference *prev = (proxy == NULL) ? ref : proxy;
594 if (prev == NULL)
595 insert_head(result, list);
596 else
597 insert_after(result, prev);
599 PyObject_GC_Track(result);
602 return (PyObject *) result;
606 PyObject *
607 PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
609 PyWeakReference *result = NULL;
610 PyWeakReference **list;
611 PyWeakReference *ref, *proxy;
613 if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) {
614 PyErr_Format(PyExc_TypeError,
615 "cannot create weak reference to '%s' object",
616 ob->ob_type->tp_name);
617 return NULL;
619 list = GET_WEAKREFS_LISTPTR(ob);
620 get_basic_refs(*list, &ref, &proxy);
621 if (callback == NULL)
622 /* attempt to return an existing weak reference if it exists */
623 result = proxy;
624 if (result != NULL)
625 Py_XINCREF(result);
626 else {
627 result = new_weakref();
628 if (result != NULL) {
629 PyWeakReference *prev;
631 if (PyCallable_Check(ob))
632 result->ob_type = &_PyWeakref_CallableProxyType;
633 else
634 result->ob_type = &_PyWeakref_ProxyType;
635 result->wr_object = ob;
636 Py_XINCREF(callback);
637 result->wr_callback = callback;
638 if (callback == NULL)
639 prev = ref;
640 else
641 prev = (proxy == NULL) ? ref : proxy;
643 if (prev == NULL)
644 insert_head(result, list);
645 else
646 insert_after(result, prev);
647 PyObject_GC_Track(result);
650 return (PyObject *) result;
654 PyObject *
655 PyWeakref_GetObject(PyObject *ref)
657 if (ref == NULL || !PyWeakref_Check(ref)) {
658 PyErr_BadInternalCall();
659 return NULL;
661 return PyWeakref_GET_OBJECT(ref);
665 static void
666 handle_callback(PyWeakReference *ref, PyObject *callback)
668 PyObject *cbresult = PyObject_CallFunction(callback, "O", ref);
670 if (cbresult == NULL)
671 PyErr_WriteUnraisable(callback);
672 else
673 Py_DECREF(cbresult);
676 /* This function is called by the tp_dealloc handler to clear weak references.
678 * This iterates through the weak references for 'object' and calls callbacks
679 * for those references which have one. It returns when all callbacks have
680 * been attempted.
682 void
683 PyObject_ClearWeakRefs(PyObject *object)
685 PyWeakReference **list;
687 if (object == NULL
688 || !PyType_SUPPORTS_WEAKREFS(object->ob_type)
689 || object->ob_refcnt != 0) {
690 PyErr_BadInternalCall();
691 return;
693 list = GET_WEAKREFS_LISTPTR(object);
694 /* Remove the callback-less basic and proxy references */
695 if (*list != NULL && (*list)->wr_callback == NULL) {
696 clear_weakref(*list);
697 if (*list != NULL && (*list)->wr_callback == NULL)
698 clear_weakref(*list);
700 if (*list != NULL) {
701 PyWeakReference *current = *list;
702 int count = _PyWeakref_GetWeakrefCount(current);
703 int restore_error = PyErr_Occurred() ? 1 : 0;
704 PyObject *err_type, *err_value, *err_tb;
706 if (restore_error)
707 PyErr_Fetch(&err_type, &err_value, &err_tb);
708 if (count == 1) {
709 PyObject *callback = current->wr_callback;
711 current->wr_callback = NULL;
712 clear_weakref(current);
713 handle_callback(current, callback);
714 Py_DECREF(callback);
716 else {
717 PyObject *tuple = PyTuple_New(count * 2);
718 int i = 0;
720 for (i = 0; i < count; ++i) {
721 PyWeakReference *next = current->wr_next;
723 Py_INCREF(current);
724 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
725 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
726 current->wr_callback = NULL;
727 clear_weakref(current);
728 current = next;
730 for (i = 0; i < count; ++i) {
731 PyObject *current = PyTuple_GET_ITEM(tuple, i * 2);
732 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
734 handle_callback((PyWeakReference *)current, callback);
736 Py_DECREF(tuple);
738 if (restore_error)
739 PyErr_Restore(err_type, err_value, err_tb);