On 64-bit platforms running test_struct after test_tarfile would fail
[python.git] / Objects / weakrefobject.c
blobbbeb3c070c39e1b5e226955235e0c270a2b69880
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 void
23 init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
25 self->hash = -1;
26 self->wr_object = ob;
27 Py_XINCREF(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);
37 if (result) {
38 init_weakref(result, ob, callback);
39 PyObject_GC_Track(result);
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 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;
66 self->wr_prev = NULL;
67 self->wr_next = NULL;
69 if (callback != NULL) {
70 Py_DECREF(callback);
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
84 * a sane state again.
86 void
87 _PyWeakref_ClearRef(PyWeakReference *self)
89 PyObject *callback;
91 assert(self != NULL);
92 assert(PyWeakref_Check(self));
93 /* Preserve and restore the callback around clear_weakref. */
94 callback = self->wr_callback;
95 self->wr_callback = NULL;
96 clear_weakref(self);
97 self->wr_callback = callback;
100 static void
101 weakref_dealloc(PyObject *self)
103 PyObject_GC_UnTrack(self);
104 clear_weakref((PyWeakReference *) self);
105 self->ob_type->tp_free(self);
109 static int
110 gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
112 Py_VISIT(self->wr_callback);
113 return 0;
117 static int
118 gc_clear(PyWeakReference *self)
120 clear_weakref(self);
121 return 0;
125 static PyObject *
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);
132 Py_INCREF(object);
133 return (object);
135 return NULL;
139 static long
140 weakref_hash(PyWeakReference *self)
142 if (self->hash != -1)
143 return self->hash;
144 if (PyWeakref_GET_OBJECT(self) == Py_None) {
145 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
146 return -1;
148 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
149 return self->hash;
153 static PyObject *
154 weakref_repr(PyWeakReference *self)
156 char buffer[256];
157 if (PyWeakref_GET_OBJECT(self) == Py_None) {
158 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
160 else {
161 char *name = NULL;
162 PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
163 "__name__");
164 if (nameobj == NULL)
165 PyErr_Clear();
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>",
171 self,
172 PyWeakref_GET_OBJECT(self)->ob_type->tp_name,
173 PyWeakref_GET_OBJECT(self),
174 name);
175 Py_XDECREF(nameobj);
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. */
184 static PyObject *
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;
194 Py_INCREF(res);
195 return res;
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.
206 static void
207 get_basic_refs(PyWeakReference *head,
208 PyWeakReference **refp, PyWeakReference **proxyp)
210 *refp = NULL;
211 *proxyp = NULL;
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
216 little. */
217 if (PyWeakref_CheckRefExact(head)) {
218 *refp = head;
219 head = head->wr_next;
221 if (head != NULL
222 && head->wr_callback == NULL
223 && PyWeakref_CheckProxy(head)) {
224 *proxyp = head;
225 /* head = head->wr_next; */
230 /* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
231 static void
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.
244 static void
245 insert_head(PyWeakReference *newref, PyWeakReference **list)
247 PyWeakReference *next = *list;
249 newref->wr_prev = NULL;
250 newref->wr_next = next;
251 if (next != NULL)
252 next->wr_prev = newref;
253 *list = newref;
256 static int
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);
264 static PyObject *
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);
278 return NULL;
280 if (callback == Py_None)
281 callback = NULL;
282 list = GET_WEAKREFS_LISTPTR(ob);
283 get_basic_refs(*list, &ref, &proxy);
284 if (callback == NULL && type == &_PyWeakref_RefType) {
285 if (ref != NULL) {
286 /* We can re-use an existing reference. */
287 Py_INCREF(ref);
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
296 them. */
297 self = (PyWeakReference *) (type->tp_alloc(type, 0));
298 if (self != NULL) {
299 init_weakref(self, ob, callback);
300 if (callback == NULL && type == &_PyWeakref_RefType) {
301 insert_head(self, list);
303 else {
304 PyWeakReference *prev;
306 get_basic_refs(*list, &ref, &proxy);
307 prev = (proxy == NULL) ? ref : proxy;
308 if (prev == NULL)
309 insert_head(self, list);
310 else
311 insert_after(self, prev);
315 return (PyObject *)self;
318 static int
319 weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
321 PyObject *tmp;
323 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
324 return 0;
325 else
326 return 1;
330 PyTypeObject
331 _PyWeakref_RefType = {
332 PyObject_HEAD_INIT(&PyType_Type)
334 "weakref",
335 sizeof(PyWeakReference),
337 weakref_dealloc, /*tp_dealloc*/
338 0, /*tp_print*/
339 0, /*tp_getattr*/
340 0, /*tp_setattr*/
341 0, /*tp_compare*/
342 (reprfunc)weakref_repr, /*tp_repr*/
343 0, /*tp_as_number*/
344 0, /*tp_as_sequence*/
345 0, /*tp_as_mapping*/
346 (hashfunc)weakref_hash, /*tp_hash*/
347 (ternaryfunc)weakref_call, /*tp_call*/
348 0, /*tp_str*/
349 0, /*tp_getattro*/
350 0, /*tp_setattro*/
351 0, /*tp_as_buffer*/
352 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
353 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
354 0, /*tp_doc*/
355 (traverseproc)gc_traverse, /*tp_traverse*/
356 (inquiry)gc_clear, /*tp_clear*/
357 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
358 0, /*tp_weaklistoffset*/
359 0, /*tp_iter*/
360 0, /*tp_iternext*/
361 0, /*tp_methods*/
362 0, /*tp_members*/
363 0, /*tp_getset*/
364 0, /*tp_base*/
365 0, /*tp_dict*/
366 0, /*tp_descr_get*/
367 0, /*tp_descr_set*/
368 0, /*tp_dictoffset*/
369 weakref___init__, /*tp_init*/
370 PyType_GenericAlloc, /*tp_alloc*/
371 weakref___new__, /*tp_new*/
372 PyObject_GC_Del, /*tp_free*/
376 static int
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");
382 return 0;
384 return 1;
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.
392 #define UNWRAP(o) \
393 if (PyWeakref_CheckProxy(o)) { \
394 if (!proxy_checkref((PyWeakReference *)o)) \
395 return NULL; \
396 o = PyWeakref_GET_OBJECT(o); \
399 #define UNWRAP_I(o) \
400 if (PyWeakref_CheckProxy(o)) { \
401 if (!proxy_checkref((PyWeakReference *)o)) \
402 return -1; \
403 o = PyWeakref_GET_OBJECT(o); \
406 #define WRAP_UNARY(method, generic) \
407 static PyObject * \
408 method(PyObject *proxy) { \
409 UNWRAP(proxy); \
410 return generic(proxy); \
413 #define WRAP_BINARY(method, generic) \
414 static PyObject * \
415 method(PyObject *x, PyObject *y) { \
416 UNWRAP(x); \
417 UNWRAP(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) \
425 static PyObject * \
426 method(PyObject *proxy, PyObject *v, PyObject *w) { \
427 UNWRAP(proxy); \
428 UNWRAP(v); \
429 if (w != NULL) \
430 UNWRAP(w); \
431 return generic(proxy, v, w); \
435 /* direct slots */
437 WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
438 WRAP_UNARY(proxy_str, PyObject_Str)
439 WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
441 static PyObject *
442 proxy_repr(PyWeakReference *proxy)
444 char buf[160];
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);
453 static int
454 proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
456 if (!proxy_checkref(proxy))
457 return -1;
458 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
461 static int
462 proxy_compare(PyObject *proxy, PyObject *v)
464 UNWRAP_I(proxy);
465 UNWRAP_I(v);
466 return PyObject_Compare(proxy, v);
469 /* number slots */
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)
501 static int
502 proxy_nonzero(PyWeakReference *proxy)
504 PyObject *o = PyWeakref_GET_OBJECT(proxy);
505 if (!proxy_checkref(proxy))
506 return -1;
507 return PyObject_IsTrue(o);
510 static void
511 proxy_dealloc(PyWeakReference *self)
513 if (self->wr_callback != NULL)
514 PyObject_GC_UnTrack((PyObject *)self);
515 clear_weakref(self);
516 PyObject_GC_Del(self);
519 /* sequence slots */
521 static PyObject *
522 proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
524 if (!proxy_checkref(proxy))
525 return NULL;
526 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
529 static int
530 proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
532 if (!proxy_checkref(proxy))
533 return -1;
534 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
537 static int
538 proxy_contains(PyWeakReference *proxy, PyObject *value)
540 if (!proxy_checkref(proxy))
541 return -1;
542 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
546 /* mapping slots */
548 static Py_ssize_t
549 proxy_length(PyWeakReference *proxy)
551 if (!proxy_checkref(proxy))
552 return -1;
553 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
556 WRAP_BINARY(proxy_getitem, PyObject_GetItem)
558 static int
559 proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
561 if (!proxy_checkref(proxy))
562 return -1;
564 if (value == NULL)
565 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
566 else
567 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
570 /* iterator slots */
572 static PyObject *
573 proxy_iter(PyWeakReference *proxy)
575 if (!proxy_checkref(proxy))
576 return NULL;
577 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
580 static PyObject *
581 proxy_iternext(PyWeakReference *proxy)
583 if (!proxy_checkref(proxy))
584 return NULL;
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*/
606 proxy_or, /*nb_or*/
607 0, /*nb_coerce*/
608 proxy_int, /*nb_int*/
609 proxy_long, /*nb_long*/
610 proxy_float, /*nb_float*/
611 0, /*nb_oct*/
612 0, /*nb_hex*/
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*/
628 0, /*sq_concat*/
629 0, /*sq_repeat*/
630 0, /*sq_item*/
631 (ssizessizeargfunc)proxy_slice, /*sq_slice*/
632 0, /*sq_ass_item*/
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*/
644 PyTypeObject
645 _PyWeakref_ProxyType = {
646 PyObject_HEAD_INIT(&PyType_Type)
648 "weakproxy",
649 sizeof(PyWeakReference),
651 /* methods */
652 (destructor)proxy_dealloc, /* tp_dealloc */
653 0, /* tp_print */
654 0, /* tp_getattr */
655 0, /* tp_setattr */
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 */
661 0, /* tp_hash */
662 0, /* tp_call */
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 */
669 0, /* tp_doc */
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 */
679 PyTypeObject
680 _PyWeakref_CallableProxyType = {
681 PyObject_HEAD_INIT(&PyType_Type)
683 "weakcallableproxy",
684 sizeof(PyWeakReference),
686 /* methods */
687 (destructor)proxy_dealloc, /* tp_dealloc */
688 0, /* tp_print */
689 0, /* tp_getattr */
690 0, /* tp_setattr */
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 */
696 0, /* tp_hash */
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 */
704 0, /* tp_doc */
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 */
715 PyObject *
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);
726 return NULL;
728 list = GET_WEAKREFS_LISTPTR(ob);
729 get_basic_refs(*list, &ref, &proxy);
730 if (callback == Py_None)
731 callback = NULL;
732 if (callback == NULL)
733 /* return existing weak reference if it exists */
734 result = ref;
735 if (result != NULL)
736 Py_INCREF(result);
737 else {
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
742 them. */
743 result = new_weakref(ob, callback);
744 if (result != NULL) {
745 get_basic_refs(*list, &ref, &proxy);
746 if (callback == NULL) {
747 if (ref == NULL)
748 insert_head(result, list);
749 else {
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. */
754 Py_DECREF(result);
755 Py_INCREF(ref);
756 result = ref;
759 else {
760 PyWeakReference *prev;
762 prev = (proxy == NULL) ? ref : proxy;
763 if (prev == NULL)
764 insert_head(result, list);
765 else
766 insert_after(result, prev);
770 return (PyObject *) result;
774 PyObject *
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);
785 return NULL;
787 list = GET_WEAKREFS_LISTPTR(ob);
788 get_basic_refs(*list, &ref, &proxy);
789 if (callback == Py_None)
790 callback = NULL;
791 if (callback == NULL)
792 /* attempt to return an existing weak reference if it exists */
793 result = proxy;
794 if (result != NULL)
795 Py_INCREF(result);
796 else {
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
801 them. */
802 result = new_weakref(ob, callback);
803 if (result != NULL) {
804 PyWeakReference *prev;
806 if (PyCallable_Check(ob))
807 result->ob_type = &_PyWeakref_CallableProxyType;
808 else
809 result->ob_type = &_PyWeakref_ProxyType;
810 get_basic_refs(*list, &ref, &proxy);
811 if (callback == NULL) {
812 if (proxy != 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. */
817 Py_DECREF(result);
818 Py_INCREF(result = proxy);
819 goto skip_insert;
821 prev = ref;
823 else
824 prev = (proxy == NULL) ? ref : proxy;
826 if (prev == NULL)
827 insert_head(result, list);
828 else
829 insert_after(result, prev);
830 skip_insert:
834 return (PyObject *) result;
838 PyObject *
839 PyWeakref_GetObject(PyObject *ref)
841 if (ref == NULL || !PyWeakref_Check(ref)) {
842 PyErr_BadInternalCall();
843 return NULL;
845 return PyWeakref_GET_OBJECT(ref);
848 /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
849 * handle_weakrefs().
851 static void
852 handle_callback(PyWeakReference *ref, PyObject *callback)
854 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
856 if (cbresult == NULL)
857 PyErr_WriteUnraisable(callback);
858 else
859 Py_DECREF(cbresult);
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
866 * been attempted.
868 void
869 PyObject_ClearWeakRefs(PyObject *object)
871 PyWeakReference **list;
873 if (object == NULL
874 || !PyType_SUPPORTS_WEAKREFS(object->ob_type)
875 || object->ob_refcnt != 0) {
876 PyErr_BadInternalCall();
877 return;
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);
886 if (*list != NULL) {
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;
892 if (restore_error)
893 PyErr_Fetch(&err_type, &err_value, &err_tb);
894 if (count == 1) {
895 PyObject *callback = current->wr_callback;
897 current->wr_callback = NULL;
898 clear_weakref(current);
899 if (callback != NULL) {
900 handle_callback(current, callback);
901 Py_DECREF(callback);
904 else {
905 PyObject *tuple;
906 Py_ssize_t i = 0;
908 tuple = PyTuple_New(count * 2);
909 if (tuple == NULL) {
910 if (restore_error)
911 PyErr_Fetch(&err_type, &err_value, &err_tb);
912 return;
915 for (i = 0; i < count; ++i) {
916 PyWeakReference *next = current->wr_next;
918 Py_INCREF(current);
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);
923 current = next;
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);
933 Py_DECREF(tuple);
935 if (restore_error)
936 PyErr_Restore(err_type, err_value, err_tb);