Updated for hfsplus module, new gusi libs.
[python/dscho.git] / Objects / weakrefobject.c
blob9a94fd4fc5b205fa4f8ffd356c2f8abdb93868b7
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 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(PyWeakReference *proxy, PyObject *v)
289 if (!proxy_checkref(proxy))
290 return -1;
291 return PyObject_Compare(PyWeakref_GET_OBJECT(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 (cmpfunc)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 (cmpfunc)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();
577 if (result != NULL) {
578 Py_XINCREF(callback);
579 result->wr_callback = callback;
580 result->wr_object = ob;
581 if (callback == NULL) {
582 insert_head(result, list);
584 else {
585 PyWeakReference *prev = (proxy == NULL) ? ref : proxy;
587 if (prev == NULL)
588 insert_head(result, list);
589 else
590 insert_after(result, prev);
592 PyObject_GC_Track(result);
595 return (PyObject *) result;
599 PyObject *
600 PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
602 PyWeakReference *result = NULL;
603 PyWeakReference **list;
604 PyWeakReference *ref, *proxy;
606 if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) {
607 PyErr_Format(PyExc_TypeError,
608 "cannot create weak reference to '%s' object",
609 ob->ob_type->tp_name);
610 return NULL;
612 list = GET_WEAKREFS_LISTPTR(ob);
613 get_basic_refs(*list, &ref, &proxy);
614 if (callback == NULL)
615 /* attempt to return an existing weak reference if it exists */
616 result = proxy;
617 if (result != NULL)
618 Py_XINCREF(result);
619 else {
620 result = new_weakref();
621 if (result != NULL) {
622 PyWeakReference *prev;
624 if (PyCallable_Check(ob))
625 result->ob_type = &_PyWeakref_CallableProxyType;
626 else
627 result->ob_type = &_PyWeakref_ProxyType;
628 result->wr_object = ob;
629 Py_XINCREF(callback);
630 result->wr_callback = callback;
631 if (callback == NULL)
632 prev = ref;
633 else
634 prev = (proxy == NULL) ? ref : proxy;
636 if (prev == NULL)
637 insert_head(result, list);
638 else
639 insert_after(result, prev);
640 PyObject_GC_Track(result);
643 return (PyObject *) result;
647 PyObject *
648 PyWeakref_GetObject(PyObject *ref)
650 if (ref == NULL || !PyWeakref_Check(ref)) {
651 PyErr_BadInternalCall();
652 return NULL;
654 return PyWeakref_GET_OBJECT(ref);
658 static void
659 handle_callback(PyWeakReference *ref, PyObject *callback)
661 PyObject *cbresult = PyObject_CallFunction(callback, "O", ref);
663 if (cbresult == NULL)
664 PyErr_WriteUnraisable(callback);
665 else
666 Py_DECREF(cbresult);
669 /* This function is called by the tp_dealloc handler to clear weak references.
671 * This iterates through the weak references for 'object' and calls callbacks
672 * for those references which have one. It returns when all callbacks have
673 * been attempted.
675 void
676 PyObject_ClearWeakRefs(PyObject *object)
678 PyWeakReference **list;
680 if (object == NULL
681 || !PyType_SUPPORTS_WEAKREFS(object->ob_type)
682 || object->ob_refcnt != 0) {
683 PyErr_BadInternalCall();
684 return;
686 list = GET_WEAKREFS_LISTPTR(object);
687 /* Remove the callback-less basic and proxy references */
688 if (*list != NULL && (*list)->wr_callback == NULL) {
689 clear_weakref(*list);
690 if (*list != NULL && (*list)->wr_callback == NULL)
691 clear_weakref(*list);
693 if (*list != NULL) {
694 PyWeakReference *current = *list;
695 int count = _PyWeakref_GetWeakrefCount(current);
696 int restore_error = PyErr_Occurred() ? 1 : 0;
697 PyObject *err_type, *err_value, *err_tb;
699 if (restore_error)
700 PyErr_Fetch(&err_type, &err_value, &err_tb);
701 if (count == 1) {
702 PyObject *callback = current->wr_callback;
704 current->wr_callback = NULL;
705 clear_weakref(current);
706 handle_callback(current, callback);
707 Py_DECREF(callback);
709 else {
710 PyObject *tuple = PyTuple_New(count * 2);
711 int i = 0;
713 for (i = 0; i < count; ++i) {
714 PyWeakReference *next = current->wr_next;
716 Py_INCREF(current);
717 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
718 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
719 current->wr_callback = NULL;
720 clear_weakref(current);
721 current = next;
723 for (i = 0; i < count; ++i) {
724 PyObject *current = PyTuple_GET_ITEM(tuple, i * 2);
725 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
727 handle_callback((PyWeakReference *)current, callback);
729 Py_DECREF(tuple);
731 if (restore_error)
732 PyErr_Restore(err_type, err_value, err_tb);