Merged revisions 78818 via svnmerge from
[python/dscho.git] / Objects / weakrefobject.c
blob27f015d3a0fd637496403f9ed9f7f3ca18acd35b
1 #include "Python.h"
2 #include "structmember.h"
5 #define GET_WEAKREFS_LISTPTR(o) \
6 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
9 Py_ssize_t
10 _PyWeakref_GetWeakrefCount(PyWeakReference *head)
12 Py_ssize_t 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 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
61 then the weakref list itself (and thus the value of *list) will
62 end up being set to NULL. */
63 *list = self->wr_next;
64 self->wr_object = Py_None;
65 if (self->wr_prev != NULL)
66 self->wr_prev->wr_next = self->wr_next;
67 if (self->wr_next != NULL)
68 self->wr_next->wr_prev = self->wr_prev;
69 self->wr_prev = NULL;
70 self->wr_next = NULL;
72 if (callback != NULL) {
73 Py_DECREF(callback);
74 self->wr_callback = NULL;
78 /* Cyclic gc uses this to *just* clear the passed-in reference, leaving
79 * the callback intact and uncalled. It must be possible to call self's
80 * tp_dealloc() after calling this, so self has to be left in a sane enough
81 * state for that to work. We expect tp_dealloc to decref the callback
82 * then. The reason for not letting clear_weakref() decref the callback
83 * right now is that if the callback goes away, that may in turn trigger
84 * another callback (if a weak reference to the callback exists) -- running
85 * arbitrary Python code in the middle of gc is a disaster. The convolution
86 * here allows gc to delay triggering such callbacks until the world is in
87 * a sane state again.
89 void
90 _PyWeakref_ClearRef(PyWeakReference *self)
92 PyObject *callback;
94 assert(self != NULL);
95 assert(PyWeakref_Check(self));
96 /* Preserve and restore the callback around clear_weakref. */
97 callback = self->wr_callback;
98 self->wr_callback = NULL;
99 clear_weakref(self);
100 self->wr_callback = callback;
103 static void
104 weakref_dealloc(PyObject *self)
106 PyObject_GC_UnTrack(self);
107 clear_weakref((PyWeakReference *) self);
108 Py_TYPE(self)->tp_free(self);
112 static int
113 gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
115 Py_VISIT(self->wr_callback);
116 return 0;
120 static int
121 gc_clear(PyWeakReference *self)
123 clear_weakref(self);
124 return 0;
128 static PyObject *
129 weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
131 static char *kwlist[] = {NULL};
133 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
134 PyObject *object = PyWeakref_GET_OBJECT(self);
135 Py_INCREF(object);
136 return (object);
138 return NULL;
142 static long
143 weakref_hash(PyWeakReference *self)
145 if (self->hash != -1)
146 return self->hash;
147 if (PyWeakref_GET_OBJECT(self) == Py_None) {
148 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
149 return -1;
151 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
152 return self->hash;
156 static PyObject *
157 weakref_repr(PyWeakReference *self)
159 char buffer[256];
160 if (PyWeakref_GET_OBJECT(self) == Py_None) {
161 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
163 else {
164 char *name = NULL;
165 PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
166 "__name__");
167 if (nameobj == NULL)
168 PyErr_Clear();
169 else if (PyUnicode_Check(nameobj))
170 name = _PyUnicode_AsString(nameobj);
171 PyOS_snprintf(buffer, sizeof(buffer),
172 name ? "<weakref at %p; to '%.50s' at %p (%s)>"
173 : "<weakref at %p; to '%.50s' at %p>",
174 self,
175 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
176 PyWeakref_GET_OBJECT(self),
177 name);
178 Py_XDECREF(nameobj);
180 return PyUnicode_FromString(buffer);
183 /* Weak references only support equality, not ordering. Two weak references
184 are equal if the underlying objects are equal. If the underlying object has
185 gone away, they are equal if they are identical. */
187 static PyObject *
188 weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
190 if ((op != Py_EQ && op != Py_NE) ||
191 !PyWeakref_Check(self) ||
192 !PyWeakref_Check(other)) {
193 Py_INCREF(Py_NotImplemented);
194 return Py_NotImplemented;
196 if (PyWeakref_GET_OBJECT(self) == Py_None
197 || PyWeakref_GET_OBJECT(other) == Py_None) {
198 PyObject *res = self==other ? Py_True : Py_False;
199 Py_INCREF(res);
200 return res;
202 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
203 PyWeakref_GET_OBJECT(other), op);
206 /* Given the head of an object's list of weak references, extract the
207 * two callback-less refs (ref and proxy). Used to determine if the
208 * shared references exist and to determine the back link for newly
209 * inserted references.
211 static void
212 get_basic_refs(PyWeakReference *head,
213 PyWeakReference **refp, PyWeakReference **proxyp)
215 *refp = NULL;
216 *proxyp = NULL;
218 if (head != NULL && head->wr_callback == NULL) {
219 /* We need to be careful that the "basic refs" aren't
220 subclasses of the main types. That complicates this a
221 little. */
222 if (PyWeakref_CheckRefExact(head)) {
223 *refp = head;
224 head = head->wr_next;
226 if (head != NULL
227 && head->wr_callback == NULL
228 && PyWeakref_CheckProxy(head)) {
229 *proxyp = head;
230 /* head = head->wr_next; */
235 /* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
236 static void
237 insert_after(PyWeakReference *newref, PyWeakReference *prev)
239 newref->wr_prev = prev;
240 newref->wr_next = prev->wr_next;
241 if (prev->wr_next != NULL)
242 prev->wr_next->wr_prev = newref;
243 prev->wr_next = newref;
246 /* Insert 'newref' at the head of the list; 'list' points to the variable
247 * that stores the head.
249 static void
250 insert_head(PyWeakReference *newref, PyWeakReference **list)
252 PyWeakReference *next = *list;
254 newref->wr_prev = NULL;
255 newref->wr_next = next;
256 if (next != NULL)
257 next->wr_prev = newref;
258 *list = newref;
261 static int
262 parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
263 PyObject **obp, PyObject **callbackp)
265 /* XXX Should check that kwargs == NULL or is empty. */
266 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
269 static PyObject *
270 weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
272 PyWeakReference *self = NULL;
273 PyObject *ob, *callback = NULL;
275 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
276 PyWeakReference *ref, *proxy;
277 PyWeakReference **list;
279 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
280 PyErr_Format(PyExc_TypeError,
281 "cannot create weak reference to '%s' object",
282 Py_TYPE(ob)->tp_name);
283 return NULL;
285 if (callback == Py_None)
286 callback = NULL;
287 list = GET_WEAKREFS_LISTPTR(ob);
288 get_basic_refs(*list, &ref, &proxy);
289 if (callback == NULL && type == &_PyWeakref_RefType) {
290 if (ref != NULL) {
291 /* We can re-use an existing reference. */
292 Py_INCREF(ref);
293 return (PyObject *)ref;
296 /* We have to create a new reference. */
297 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
298 list on ob can be mutated. This means that the ref and
299 proxy pointers we got back earlier may have been collected,
300 so we need to compute these values again before we use
301 them. */
302 self = (PyWeakReference *) (type->tp_alloc(type, 0));
303 if (self != NULL) {
304 init_weakref(self, ob, callback);
305 if (callback == NULL && type == &_PyWeakref_RefType) {
306 insert_head(self, list);
308 else {
309 PyWeakReference *prev;
311 get_basic_refs(*list, &ref, &proxy);
312 prev = (proxy == NULL) ? ref : proxy;
313 if (prev == NULL)
314 insert_head(self, list);
315 else
316 insert_after(self, prev);
320 return (PyObject *)self;
323 static int
324 weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
326 PyObject *tmp;
328 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
329 return 0;
330 else
331 return -1;
335 PyTypeObject
336 _PyWeakref_RefType = {
337 PyVarObject_HEAD_INIT(&PyType_Type, 0)
338 "weakref",
339 sizeof(PyWeakReference),
341 weakref_dealloc, /*tp_dealloc*/
342 0, /*tp_print*/
343 0, /*tp_getattr*/
344 0, /*tp_setattr*/
345 0, /*tp_reserved*/
346 (reprfunc)weakref_repr, /*tp_repr*/
347 0, /*tp_as_number*/
348 0, /*tp_as_sequence*/
349 0, /*tp_as_mapping*/
350 (hashfunc)weakref_hash, /*tp_hash*/
351 (ternaryfunc)weakref_call, /*tp_call*/
352 0, /*tp_str*/
353 0, /*tp_getattro*/
354 0, /*tp_setattro*/
355 0, /*tp_as_buffer*/
356 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
357 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
358 0, /*tp_doc*/
359 (traverseproc)gc_traverse, /*tp_traverse*/
360 (inquiry)gc_clear, /*tp_clear*/
361 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
362 0, /*tp_weaklistoffset*/
363 0, /*tp_iter*/
364 0, /*tp_iternext*/
365 0, /*tp_methods*/
366 0, /*tp_members*/
367 0, /*tp_getset*/
368 0, /*tp_base*/
369 0, /*tp_dict*/
370 0, /*tp_descr_get*/
371 0, /*tp_descr_set*/
372 0, /*tp_dictoffset*/
373 weakref___init__, /*tp_init*/
374 PyType_GenericAlloc, /*tp_alloc*/
375 weakref___new__, /*tp_new*/
376 PyObject_GC_Del, /*tp_free*/
380 static int
381 proxy_checkref(PyWeakReference *proxy)
383 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
384 PyErr_SetString(PyExc_ReferenceError,
385 "weakly-referenced object no longer exists");
386 return 0;
388 return 1;
392 /* If a parameter is a proxy, check that it is still "live" and wrap it,
393 * replacing the original value with the raw object. Raises ReferenceError
394 * if the param is a dead proxy.
396 #define UNWRAP(o) \
397 if (PyWeakref_CheckProxy(o)) { \
398 if (!proxy_checkref((PyWeakReference *)o)) \
399 return NULL; \
400 o = PyWeakref_GET_OBJECT(o); \
403 #define UNWRAP_I(o) \
404 if (PyWeakref_CheckProxy(o)) { \
405 if (!proxy_checkref((PyWeakReference *)o)) \
406 return -1; \
407 o = PyWeakref_GET_OBJECT(o); \
410 #define WRAP_UNARY(method, generic) \
411 static PyObject * \
412 method(PyObject *proxy) { \
413 UNWRAP(proxy); \
414 return generic(proxy); \
417 #define WRAP_BINARY(method, generic) \
418 static PyObject * \
419 method(PyObject *x, PyObject *y) { \
420 UNWRAP(x); \
421 UNWRAP(y); \
422 return generic(x, y); \
425 /* Note that the third arg needs to be checked for NULL since the tp_call
426 * slot can receive NULL for this arg.
428 #define WRAP_TERNARY(method, generic) \
429 static PyObject * \
430 method(PyObject *proxy, PyObject *v, PyObject *w) { \
431 UNWRAP(proxy); \
432 UNWRAP(v); \
433 if (w != NULL) \
434 UNWRAP(w); \
435 return generic(proxy, v, w); \
438 #define WRAP_METHOD(method, special) \
439 static PyObject * \
440 method(PyObject *proxy) { \
441 UNWRAP(proxy); \
442 return PyObject_CallMethod(proxy, special, ""); \
446 /* direct slots */
448 WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
449 WRAP_UNARY(proxy_str, PyObject_Str)
450 WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
452 static PyObject *
453 proxy_repr(PyWeakReference *proxy)
455 char buf[160];
456 PyOS_snprintf(buf, sizeof(buf),
457 "<weakproxy at %p to %.100s at %p>", proxy,
458 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
459 PyWeakref_GET_OBJECT(proxy));
460 return PyUnicode_FromString(buf);
464 static int
465 proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
467 if (!proxy_checkref(proxy))
468 return -1;
469 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
472 static PyObject *
473 proxy_richcompare(PyObject *proxy, PyObject *v, int op)
475 UNWRAP(proxy);
476 UNWRAP(v);
477 return PyObject_RichCompare(proxy, v, op);
480 /* number slots */
481 WRAP_BINARY(proxy_add, PyNumber_Add)
482 WRAP_BINARY(proxy_sub, PyNumber_Subtract)
483 WRAP_BINARY(proxy_mul, PyNumber_Multiply)
484 WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
485 WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
486 WRAP_BINARY(proxy_mod, PyNumber_Remainder)
487 WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
488 WRAP_TERNARY(proxy_pow, PyNumber_Power)
489 WRAP_UNARY(proxy_neg, PyNumber_Negative)
490 WRAP_UNARY(proxy_pos, PyNumber_Positive)
491 WRAP_UNARY(proxy_abs, PyNumber_Absolute)
492 WRAP_UNARY(proxy_invert, PyNumber_Invert)
493 WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
494 WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
495 WRAP_BINARY(proxy_and, PyNumber_And)
496 WRAP_BINARY(proxy_xor, PyNumber_Xor)
497 WRAP_BINARY(proxy_or, PyNumber_Or)
498 WRAP_UNARY(proxy_int, PyNumber_Long)
499 WRAP_UNARY(proxy_float, PyNumber_Float)
500 WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
501 WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
502 WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
503 WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
504 WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
505 WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
506 WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
507 WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
508 WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
509 WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
510 WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
511 WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
512 WRAP_UNARY(proxy_index, PyNumber_Index)
514 static int
515 proxy_bool(PyWeakReference *proxy)
517 PyObject *o = PyWeakref_GET_OBJECT(proxy);
518 if (!proxy_checkref(proxy))
519 return -1;
520 return PyObject_IsTrue(o);
523 static void
524 proxy_dealloc(PyWeakReference *self)
526 if (self->wr_callback != NULL)
527 PyObject_GC_UnTrack((PyObject *)self);
528 clear_weakref(self);
529 PyObject_GC_Del(self);
532 /* sequence slots */
534 static int
535 proxy_contains(PyWeakReference *proxy, PyObject *value)
537 if (!proxy_checkref(proxy))
538 return -1;
539 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
543 /* mapping slots */
545 static Py_ssize_t
546 proxy_length(PyWeakReference *proxy)
548 if (!proxy_checkref(proxy))
549 return -1;
550 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
553 WRAP_BINARY(proxy_getitem, PyObject_GetItem)
555 static int
556 proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
558 if (!proxy_checkref(proxy))
559 return -1;
561 if (value == NULL)
562 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
563 else
564 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
567 /* iterator slots */
569 static PyObject *
570 proxy_iter(PyWeakReference *proxy)
572 if (!proxy_checkref(proxy))
573 return NULL;
574 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
577 static PyObject *
578 proxy_iternext(PyWeakReference *proxy)
580 if (!proxy_checkref(proxy))
581 return NULL;
582 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
586 WRAP_METHOD(proxy_bytes, "__bytes__");
589 static PyMethodDef proxy_methods[] = {
590 {"__bytes__", (PyCFunction)proxy_bytes, METH_NOARGS},
591 {NULL, NULL}
595 static PyNumberMethods proxy_as_number = {
596 proxy_add, /*nb_add*/
597 proxy_sub, /*nb_subtract*/
598 proxy_mul, /*nb_multiply*/
599 proxy_mod, /*nb_remainder*/
600 proxy_divmod, /*nb_divmod*/
601 proxy_pow, /*nb_power*/
602 proxy_neg, /*nb_negative*/
603 proxy_pos, /*nb_positive*/
604 proxy_abs, /*nb_absolute*/
605 (inquiry)proxy_bool, /*nb_bool*/
606 proxy_invert, /*nb_invert*/
607 proxy_lshift, /*nb_lshift*/
608 proxy_rshift, /*nb_rshift*/
609 proxy_and, /*nb_and*/
610 proxy_xor, /*nb_xor*/
611 proxy_or, /*nb_or*/
612 proxy_int, /*nb_int*/
613 0, /*nb_reserved*/
614 proxy_float, /*nb_float*/
615 proxy_iadd, /*nb_inplace_add*/
616 proxy_isub, /*nb_inplace_subtract*/
617 proxy_imul, /*nb_inplace_multiply*/
618 proxy_imod, /*nb_inplace_remainder*/
619 proxy_ipow, /*nb_inplace_power*/
620 proxy_ilshift, /*nb_inplace_lshift*/
621 proxy_irshift, /*nb_inplace_rshift*/
622 proxy_iand, /*nb_inplace_and*/
623 proxy_ixor, /*nb_inplace_xor*/
624 proxy_ior, /*nb_inplace_or*/
625 proxy_floor_div, /*nb_floor_divide*/
626 proxy_true_div, /*nb_true_divide*/
627 proxy_ifloor_div, /*nb_inplace_floor_divide*/
628 proxy_itrue_div, /*nb_inplace_true_divide*/
629 proxy_index, /*nb_index*/
632 static PySequenceMethods proxy_as_sequence = {
633 (lenfunc)proxy_length, /*sq_length*/
634 0, /*sq_concat*/
635 0, /*sq_repeat*/
636 0, /*sq_item*/
637 0, /*sq_slice*/
638 0, /*sq_ass_item*/
639 0, /*sq_ass_slice*/
640 (objobjproc)proxy_contains, /* sq_contains */
643 static PyMappingMethods proxy_as_mapping = {
644 (lenfunc)proxy_length, /*mp_length*/
645 proxy_getitem, /*mp_subscript*/
646 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
650 PyTypeObject
651 _PyWeakref_ProxyType = {
652 PyVarObject_HEAD_INIT(&PyType_Type, 0)
653 "weakproxy",
654 sizeof(PyWeakReference),
656 /* methods */
657 (destructor)proxy_dealloc, /* tp_dealloc */
658 0, /* tp_print */
659 0, /* tp_getattr */
660 0, /* tp_setattr */
661 0, /* tp_reserved */
662 (reprfunc)proxy_repr, /* tp_repr */
663 &proxy_as_number, /* tp_as_number */
664 &proxy_as_sequence, /* tp_as_sequence */
665 &proxy_as_mapping, /* tp_as_mapping */
666 0, /* tp_hash */
667 0, /* tp_call */
668 proxy_str, /* tp_str */
669 proxy_getattr, /* tp_getattro */
670 (setattrofunc)proxy_setattr, /* tp_setattro */
671 0, /* tp_as_buffer */
672 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
673 0, /* tp_doc */
674 (traverseproc)gc_traverse, /* tp_traverse */
675 (inquiry)gc_clear, /* tp_clear */
676 proxy_richcompare, /* tp_richcompare */
677 0, /* tp_weaklistoffset */
678 (getiterfunc)proxy_iter, /* tp_iter */
679 (iternextfunc)proxy_iternext, /* tp_iternext */
680 proxy_methods, /* tp_methods */
684 PyTypeObject
685 _PyWeakref_CallableProxyType = {
686 PyVarObject_HEAD_INIT(&PyType_Type, 0)
687 "weakcallableproxy",
688 sizeof(PyWeakReference),
690 /* methods */
691 (destructor)proxy_dealloc, /* tp_dealloc */
692 0, /* tp_print */
693 0, /* tp_getattr */
694 0, /* tp_setattr */
695 0, /* tp_reserved */
696 (unaryfunc)proxy_repr, /* tp_repr */
697 &proxy_as_number, /* tp_as_number */
698 &proxy_as_sequence, /* tp_as_sequence */
699 &proxy_as_mapping, /* tp_as_mapping */
700 0, /* tp_hash */
701 proxy_call, /* tp_call */
702 proxy_str, /* tp_str */
703 proxy_getattr, /* tp_getattro */
704 (setattrofunc)proxy_setattr, /* tp_setattro */
705 0, /* tp_as_buffer */
706 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
707 0, /* tp_doc */
708 (traverseproc)gc_traverse, /* tp_traverse */
709 (inquiry)gc_clear, /* tp_clear */
710 proxy_richcompare, /* tp_richcompare */
711 0, /* tp_weaklistoffset */
712 (getiterfunc)proxy_iter, /* tp_iter */
713 (iternextfunc)proxy_iternext, /* tp_iternext */
718 PyObject *
719 PyWeakref_NewRef(PyObject *ob, PyObject *callback)
721 PyWeakReference *result = NULL;
722 PyWeakReference **list;
723 PyWeakReference *ref, *proxy;
725 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
726 PyErr_Format(PyExc_TypeError,
727 "cannot create weak reference to '%s' object",
728 Py_TYPE(ob)->tp_name);
729 return NULL;
731 list = GET_WEAKREFS_LISTPTR(ob);
732 get_basic_refs(*list, &ref, &proxy);
733 if (callback == Py_None)
734 callback = NULL;
735 if (callback == NULL)
736 /* return existing weak reference if it exists */
737 result = ref;
738 if (result != NULL)
739 Py_INCREF(result);
740 else {
741 /* Note: new_weakref() can trigger cyclic GC, so the weakref
742 list on ob can be mutated. This means that the ref and
743 proxy pointers we got back earlier may have been collected,
744 so we need to compute these values again before we use
745 them. */
746 result = new_weakref(ob, callback);
747 if (result != NULL) {
748 get_basic_refs(*list, &ref, &proxy);
749 if (callback == NULL) {
750 if (ref == NULL)
751 insert_head(result, list);
752 else {
753 /* Someone else added a ref without a callback
754 during GC. Return that one instead of this one
755 to avoid violating the invariants of the list
756 of weakrefs for ob. */
757 Py_DECREF(result);
758 Py_INCREF(ref);
759 result = ref;
762 else {
763 PyWeakReference *prev;
765 prev = (proxy == NULL) ? ref : proxy;
766 if (prev == NULL)
767 insert_head(result, list);
768 else
769 insert_after(result, prev);
773 return (PyObject *) result;
777 PyObject *
778 PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
780 PyWeakReference *result = NULL;
781 PyWeakReference **list;
782 PyWeakReference *ref, *proxy;
784 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
785 PyErr_Format(PyExc_TypeError,
786 "cannot create weak reference to '%s' object",
787 Py_TYPE(ob)->tp_name);
788 return NULL;
790 list = GET_WEAKREFS_LISTPTR(ob);
791 get_basic_refs(*list, &ref, &proxy);
792 if (callback == Py_None)
793 callback = NULL;
794 if (callback == NULL)
795 /* attempt to return an existing weak reference if it exists */
796 result = proxy;
797 if (result != NULL)
798 Py_INCREF(result);
799 else {
800 /* Note: new_weakref() can trigger cyclic GC, so the weakref
801 list on ob can be mutated. This means that the ref and
802 proxy pointers we got back earlier may have been collected,
803 so we need to compute these values again before we use
804 them. */
805 result = new_weakref(ob, callback);
806 if (result != NULL) {
807 PyWeakReference *prev;
809 if (PyCallable_Check(ob))
810 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
811 else
812 Py_TYPE(result) = &_PyWeakref_ProxyType;
813 get_basic_refs(*list, &ref, &proxy);
814 if (callback == NULL) {
815 if (proxy != NULL) {
816 /* Someone else added a proxy without a callback
817 during GC. Return that one instead of this one
818 to avoid violating the invariants of the list
819 of weakrefs for ob. */
820 Py_DECREF(result);
821 Py_INCREF(result = proxy);
822 goto skip_insert;
824 prev = ref;
826 else
827 prev = (proxy == NULL) ? ref : proxy;
829 if (prev == NULL)
830 insert_head(result, list);
831 else
832 insert_after(result, prev);
833 skip_insert:
837 return (PyObject *) result;
841 PyObject *
842 PyWeakref_GetObject(PyObject *ref)
844 if (ref == NULL || !PyWeakref_Check(ref)) {
845 PyErr_BadInternalCall();
846 return NULL;
848 return PyWeakref_GET_OBJECT(ref);
851 /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
852 * handle_weakrefs().
854 static void
855 handle_callback(PyWeakReference *ref, PyObject *callback)
857 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
859 if (cbresult == NULL)
860 PyErr_WriteUnraisable(callback);
861 else
862 Py_DECREF(cbresult);
865 /* This function is called by the tp_dealloc handler to clear weak references.
867 * This iterates through the weak references for 'object' and calls callbacks
868 * for those references which have one. It returns when all callbacks have
869 * been attempted.
871 void
872 PyObject_ClearWeakRefs(PyObject *object)
874 PyWeakReference **list;
876 if (object == NULL
877 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
878 || object->ob_refcnt != 0) {
879 PyErr_BadInternalCall();
880 return;
882 list = GET_WEAKREFS_LISTPTR(object);
883 /* Remove the callback-less basic and proxy references */
884 if (*list != NULL && (*list)->wr_callback == NULL) {
885 clear_weakref(*list);
886 if (*list != NULL && (*list)->wr_callback == NULL)
887 clear_weakref(*list);
889 if (*list != NULL) {
890 PyWeakReference *current = *list;
891 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
892 int restore_error = PyErr_Occurred() ? 1 : 0;
893 PyObject *err_type, *err_value, *err_tb;
895 if (restore_error)
896 PyErr_Fetch(&err_type, &err_value, &err_tb);
897 if (count == 1) {
898 PyObject *callback = current->wr_callback;
900 current->wr_callback = NULL;
901 clear_weakref(current);
902 if (callback != NULL) {
903 if (((PyObject *)current)->ob_refcnt > 0)
904 handle_callback(current, callback);
905 Py_DECREF(callback);
908 else {
909 PyObject *tuple;
910 Py_ssize_t i = 0;
912 tuple = PyTuple_New(count * 2);
913 if (tuple == NULL) {
914 if (restore_error)
915 PyErr_Fetch(&err_type, &err_value, &err_tb);
916 return;
919 for (i = 0; i < count; ++i) {
920 PyWeakReference *next = current->wr_next;
922 if (((PyObject *)current)->ob_refcnt > 0)
924 Py_INCREF(current);
925 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
926 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
928 else {
929 Py_DECREF(current->wr_callback);
931 current->wr_callback = NULL;
932 clear_weakref(current);
933 current = next;
935 for (i = 0; i < count; ++i) {
936 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
938 /* The tuple may have slots left to NULL */
939 if (callback != NULL) {
940 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
941 handle_callback((PyWeakReference *)item, callback);
944 Py_DECREF(tuple);
946 if (restore_error)
947 PyErr_Restore(err_type, err_value, err_tb);