Applying patches backported from 3.1, by Gregor Lingl.
[python.git] / Objects / weakrefobject.c
blob9cdd02178d7083cbb6e0a74cca13712c00df97cb
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 (PyString_Check(nameobj))
170 name = PyString_AS_STRING(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 PyString_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 || self->ob_type != other->ob_type) {
191 Py_INCREF(Py_NotImplemented);
192 return Py_NotImplemented;
194 if (PyWeakref_GET_OBJECT(self) == Py_None
195 || PyWeakref_GET_OBJECT(other) == Py_None) {
196 PyObject *res = self==other ? Py_True : Py_False;
197 Py_INCREF(res);
198 return res;
200 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
201 PyWeakref_GET_OBJECT(other), op);
204 /* Given the head of an object's list of weak references, extract the
205 * two callback-less refs (ref and proxy). Used to determine if the
206 * shared references exist and to determine the back link for newly
207 * inserted references.
209 static void
210 get_basic_refs(PyWeakReference *head,
211 PyWeakReference **refp, PyWeakReference **proxyp)
213 *refp = NULL;
214 *proxyp = NULL;
216 if (head != NULL && head->wr_callback == NULL) {
217 /* We need to be careful that the "basic refs" aren't
218 subclasses of the main types. That complicates this a
219 little. */
220 if (PyWeakref_CheckRefExact(head)) {
221 *refp = head;
222 head = head->wr_next;
224 if (head != NULL
225 && head->wr_callback == NULL
226 && PyWeakref_CheckProxy(head)) {
227 *proxyp = head;
228 /* head = head->wr_next; */
233 /* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
234 static void
235 insert_after(PyWeakReference *newref, PyWeakReference *prev)
237 newref->wr_prev = prev;
238 newref->wr_next = prev->wr_next;
239 if (prev->wr_next != NULL)
240 prev->wr_next->wr_prev = newref;
241 prev->wr_next = newref;
244 /* Insert 'newref' at the head of the list; 'list' points to the variable
245 * that stores the head.
247 static void
248 insert_head(PyWeakReference *newref, PyWeakReference **list)
250 PyWeakReference *next = *list;
252 newref->wr_prev = NULL;
253 newref->wr_next = next;
254 if (next != NULL)
255 next->wr_prev = newref;
256 *list = newref;
259 static int
260 parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
261 PyObject **obp, PyObject **callbackp)
263 /* XXX Should check that kwargs == NULL or is empty. */
264 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
267 static PyObject *
268 weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
270 PyWeakReference *self = NULL;
271 PyObject *ob, *callback = NULL;
273 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
274 PyWeakReference *ref, *proxy;
275 PyWeakReference **list;
277 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
278 PyErr_Format(PyExc_TypeError,
279 "cannot create weak reference to '%s' object",
280 Py_TYPE(ob)->tp_name);
281 return NULL;
283 if (callback == Py_None)
284 callback = NULL;
285 list = GET_WEAKREFS_LISTPTR(ob);
286 get_basic_refs(*list, &ref, &proxy);
287 if (callback == NULL && type == &_PyWeakref_RefType) {
288 if (ref != NULL) {
289 /* We can re-use an existing reference. */
290 Py_INCREF(ref);
291 return (PyObject *)ref;
294 /* We have to create a new reference. */
295 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
296 list on ob can be mutated. This means that the ref and
297 proxy pointers we got back earlier may have been collected,
298 so we need to compute these values again before we use
299 them. */
300 self = (PyWeakReference *) (type->tp_alloc(type, 0));
301 if (self != NULL) {
302 init_weakref(self, ob, callback);
303 if (callback == NULL && type == &_PyWeakref_RefType) {
304 insert_head(self, list);
306 else {
307 PyWeakReference *prev;
309 get_basic_refs(*list, &ref, &proxy);
310 prev = (proxy == NULL) ? ref : proxy;
311 if (prev == NULL)
312 insert_head(self, list);
313 else
314 insert_after(self, prev);
318 return (PyObject *)self;
321 static int
322 weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
324 PyObject *tmp;
326 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
327 return 0;
328 else
329 return -1;
333 PyTypeObject
334 _PyWeakref_RefType = {
335 PyVarObject_HEAD_INIT(&PyType_Type, 0)
336 "weakref",
337 sizeof(PyWeakReference),
339 weakref_dealloc, /*tp_dealloc*/
340 0, /*tp_print*/
341 0, /*tp_getattr*/
342 0, /*tp_setattr*/
343 0, /*tp_compare*/
344 (reprfunc)weakref_repr, /*tp_repr*/
345 0, /*tp_as_number*/
346 0, /*tp_as_sequence*/
347 0, /*tp_as_mapping*/
348 (hashfunc)weakref_hash, /*tp_hash*/
349 (ternaryfunc)weakref_call, /*tp_call*/
350 0, /*tp_str*/
351 0, /*tp_getattro*/
352 0, /*tp_setattro*/
353 0, /*tp_as_buffer*/
354 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
355 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
356 0, /*tp_doc*/
357 (traverseproc)gc_traverse, /*tp_traverse*/
358 (inquiry)gc_clear, /*tp_clear*/
359 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
360 0, /*tp_weaklistoffset*/
361 0, /*tp_iter*/
362 0, /*tp_iternext*/
363 0, /*tp_methods*/
364 0, /*tp_members*/
365 0, /*tp_getset*/
366 0, /*tp_base*/
367 0, /*tp_dict*/
368 0, /*tp_descr_get*/
369 0, /*tp_descr_set*/
370 0, /*tp_dictoffset*/
371 weakref___init__, /*tp_init*/
372 PyType_GenericAlloc, /*tp_alloc*/
373 weakref___new__, /*tp_new*/
374 PyObject_GC_Del, /*tp_free*/
378 static int
379 proxy_checkref(PyWeakReference *proxy)
381 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
382 PyErr_SetString(PyExc_ReferenceError,
383 "weakly-referenced object no longer exists");
384 return 0;
386 return 1;
390 /* If a parameter is a proxy, check that it is still "live" and wrap it,
391 * replacing the original value with the raw object. Raises ReferenceError
392 * if the param is a dead proxy.
394 #define UNWRAP(o) \
395 if (PyWeakref_CheckProxy(o)) { \
396 if (!proxy_checkref((PyWeakReference *)o)) \
397 return NULL; \
398 o = PyWeakref_GET_OBJECT(o); \
401 #define UNWRAP_I(o) \
402 if (PyWeakref_CheckProxy(o)) { \
403 if (!proxy_checkref((PyWeakReference *)o)) \
404 return -1; \
405 o = PyWeakref_GET_OBJECT(o); \
408 #define WRAP_UNARY(method, generic) \
409 static PyObject * \
410 method(PyObject *proxy) { \
411 UNWRAP(proxy); \
412 return generic(proxy); \
415 #define WRAP_BINARY(method, generic) \
416 static PyObject * \
417 method(PyObject *x, PyObject *y) { \
418 UNWRAP(x); \
419 UNWRAP(y); \
420 return generic(x, y); \
423 /* Note that the third arg needs to be checked for NULL since the tp_call
424 * slot can receive NULL for this arg.
426 #define WRAP_TERNARY(method, generic) \
427 static PyObject * \
428 method(PyObject *proxy, PyObject *v, PyObject *w) { \
429 UNWRAP(proxy); \
430 UNWRAP(v); \
431 if (w != NULL) \
432 UNWRAP(w); \
433 return generic(proxy, v, w); \
437 /* direct slots */
439 WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
440 WRAP_UNARY(proxy_str, PyObject_Str)
441 WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
443 static PyObject *
444 proxy_repr(PyWeakReference *proxy)
446 char buf[160];
447 PyOS_snprintf(buf, sizeof(buf),
448 "<weakproxy at %p to %.100s at %p>", proxy,
449 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
450 PyWeakref_GET_OBJECT(proxy));
451 return PyString_FromString(buf);
455 static int
456 proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
458 if (!proxy_checkref(proxy))
459 return -1;
460 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
463 static int
464 proxy_compare(PyObject *proxy, PyObject *v)
466 UNWRAP_I(proxy);
467 UNWRAP_I(v);
468 return PyObject_Compare(proxy, v);
471 /* number slots */
472 WRAP_BINARY(proxy_add, PyNumber_Add)
473 WRAP_BINARY(proxy_sub, PyNumber_Subtract)
474 WRAP_BINARY(proxy_mul, PyNumber_Multiply)
475 WRAP_BINARY(proxy_div, PyNumber_Divide)
476 WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
477 WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
478 WRAP_BINARY(proxy_mod, PyNumber_Remainder)
479 WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
480 WRAP_TERNARY(proxy_pow, PyNumber_Power)
481 WRAP_UNARY(proxy_neg, PyNumber_Negative)
482 WRAP_UNARY(proxy_pos, PyNumber_Positive)
483 WRAP_UNARY(proxy_abs, PyNumber_Absolute)
484 WRAP_UNARY(proxy_invert, PyNumber_Invert)
485 WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
486 WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
487 WRAP_BINARY(proxy_and, PyNumber_And)
488 WRAP_BINARY(proxy_xor, PyNumber_Xor)
489 WRAP_BINARY(proxy_or, PyNumber_Or)
490 WRAP_UNARY(proxy_int, PyNumber_Int)
491 WRAP_UNARY(proxy_long, PyNumber_Long)
492 WRAP_UNARY(proxy_float, PyNumber_Float)
493 WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
494 WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
495 WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
496 WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
497 WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
498 WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
499 WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
500 WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
501 WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
502 WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
503 WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
504 WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
505 WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
506 WRAP_UNARY(proxy_index, PyNumber_Index)
508 static int
509 proxy_nonzero(PyWeakReference *proxy)
511 PyObject *o = PyWeakref_GET_OBJECT(proxy);
512 if (!proxy_checkref(proxy))
513 return -1;
514 return PyObject_IsTrue(o);
517 static void
518 proxy_dealloc(PyWeakReference *self)
520 if (self->wr_callback != NULL)
521 PyObject_GC_UnTrack((PyObject *)self);
522 clear_weakref(self);
523 PyObject_GC_Del(self);
526 /* sequence slots */
528 static PyObject *
529 proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
531 if (!proxy_checkref(proxy))
532 return NULL;
533 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
536 static int
537 proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
539 if (!proxy_checkref(proxy))
540 return -1;
541 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
544 static int
545 proxy_contains(PyWeakReference *proxy, PyObject *value)
547 if (!proxy_checkref(proxy))
548 return -1;
549 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
553 /* mapping slots */
555 static Py_ssize_t
556 proxy_length(PyWeakReference *proxy)
558 if (!proxy_checkref(proxy))
559 return -1;
560 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
563 WRAP_BINARY(proxy_getitem, PyObject_GetItem)
565 static int
566 proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
568 if (!proxy_checkref(proxy))
569 return -1;
571 if (value == NULL)
572 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
573 else
574 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
577 /* iterator slots */
579 static PyObject *
580 proxy_iter(PyWeakReference *proxy)
582 if (!proxy_checkref(proxy))
583 return NULL;
584 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
587 static PyObject *
588 proxy_iternext(PyWeakReference *proxy)
590 if (!proxy_checkref(proxy))
591 return NULL;
592 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
596 static PyNumberMethods proxy_as_number = {
597 proxy_add, /*nb_add*/
598 proxy_sub, /*nb_subtract*/
599 proxy_mul, /*nb_multiply*/
600 proxy_div, /*nb_divide*/
601 proxy_mod, /*nb_remainder*/
602 proxy_divmod, /*nb_divmod*/
603 proxy_pow, /*nb_power*/
604 proxy_neg, /*nb_negative*/
605 proxy_pos, /*nb_positive*/
606 proxy_abs, /*nb_absolute*/
607 (inquiry)proxy_nonzero, /*nb_nonzero*/
608 proxy_invert, /*nb_invert*/
609 proxy_lshift, /*nb_lshift*/
610 proxy_rshift, /*nb_rshift*/
611 proxy_and, /*nb_and*/
612 proxy_xor, /*nb_xor*/
613 proxy_or, /*nb_or*/
614 0, /*nb_coerce*/
615 proxy_int, /*nb_int*/
616 proxy_long, /*nb_long*/
617 proxy_float, /*nb_float*/
618 0, /*nb_oct*/
619 0, /*nb_hex*/
620 proxy_iadd, /*nb_inplace_add*/
621 proxy_isub, /*nb_inplace_subtract*/
622 proxy_imul, /*nb_inplace_multiply*/
623 proxy_idiv, /*nb_inplace_divide*/
624 proxy_imod, /*nb_inplace_remainder*/
625 proxy_ipow, /*nb_inplace_power*/
626 proxy_ilshift, /*nb_inplace_lshift*/
627 proxy_irshift, /*nb_inplace_rshift*/
628 proxy_iand, /*nb_inplace_and*/
629 proxy_ixor, /*nb_inplace_xor*/
630 proxy_ior, /*nb_inplace_or*/
631 proxy_floor_div, /*nb_floor_divide*/
632 proxy_true_div, /*nb_true_divide*/
633 proxy_ifloor_div, /*nb_inplace_floor_divide*/
634 proxy_itrue_div, /*nb_inplace_true_divide*/
635 proxy_index, /*nb_index*/
638 static PySequenceMethods proxy_as_sequence = {
639 (lenfunc)proxy_length, /*sq_length*/
640 0, /*sq_concat*/
641 0, /*sq_repeat*/
642 0, /*sq_item*/
643 (ssizessizeargfunc)proxy_slice, /*sq_slice*/
644 0, /*sq_ass_item*/
645 (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/
646 (objobjproc)proxy_contains, /* sq_contains */
649 static PyMappingMethods proxy_as_mapping = {
650 (lenfunc)proxy_length, /*mp_length*/
651 proxy_getitem, /*mp_subscript*/
652 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
656 PyTypeObject
657 _PyWeakref_ProxyType = {
658 PyVarObject_HEAD_INIT(&PyType_Type, 0)
659 "weakproxy",
660 sizeof(PyWeakReference),
662 /* methods */
663 (destructor)proxy_dealloc, /* tp_dealloc */
664 0, /* tp_print */
665 0, /* tp_getattr */
666 0, /* tp_setattr */
667 proxy_compare, /* tp_compare */
668 (reprfunc)proxy_repr, /* tp_repr */
669 &proxy_as_number, /* tp_as_number */
670 &proxy_as_sequence, /* tp_as_sequence */
671 &proxy_as_mapping, /* tp_as_mapping */
672 0, /* tp_hash */
673 0, /* tp_call */
674 proxy_str, /* tp_str */
675 proxy_getattr, /* tp_getattro */
676 (setattrofunc)proxy_setattr, /* tp_setattro */
677 0, /* tp_as_buffer */
678 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
679 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
680 0, /* tp_doc */
681 (traverseproc)gc_traverse, /* tp_traverse */
682 (inquiry)gc_clear, /* tp_clear */
683 0, /* tp_richcompare */
684 0, /* tp_weaklistoffset */
685 (getiterfunc)proxy_iter, /* tp_iter */
686 (iternextfunc)proxy_iternext, /* tp_iternext */
690 PyTypeObject
691 _PyWeakref_CallableProxyType = {
692 PyVarObject_HEAD_INIT(&PyType_Type, 0)
693 "weakcallableproxy",
694 sizeof(PyWeakReference),
696 /* methods */
697 (destructor)proxy_dealloc, /* tp_dealloc */
698 0, /* tp_print */
699 0, /* tp_getattr */
700 0, /* tp_setattr */
701 proxy_compare, /* tp_compare */
702 (unaryfunc)proxy_repr, /* tp_repr */
703 &proxy_as_number, /* tp_as_number */
704 &proxy_as_sequence, /* tp_as_sequence */
705 &proxy_as_mapping, /* tp_as_mapping */
706 0, /* tp_hash */
707 proxy_call, /* tp_call */
708 proxy_str, /* tp_str */
709 proxy_getattr, /* tp_getattro */
710 (setattrofunc)proxy_setattr, /* tp_setattro */
711 0, /* tp_as_buffer */
712 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
713 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
714 0, /* tp_doc */
715 (traverseproc)gc_traverse, /* tp_traverse */
716 (inquiry)gc_clear, /* tp_clear */
717 0, /* tp_richcompare */
718 0, /* tp_weaklistoffset */
719 (getiterfunc)proxy_iter, /* tp_iter */
720 (iternextfunc)proxy_iternext, /* tp_iternext */
725 PyObject *
726 PyWeakref_NewRef(PyObject *ob, PyObject *callback)
728 PyWeakReference *result = NULL;
729 PyWeakReference **list;
730 PyWeakReference *ref, *proxy;
732 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
733 PyErr_Format(PyExc_TypeError,
734 "cannot create weak reference to '%s' object",
735 Py_TYPE(ob)->tp_name);
736 return NULL;
738 list = GET_WEAKREFS_LISTPTR(ob);
739 get_basic_refs(*list, &ref, &proxy);
740 if (callback == Py_None)
741 callback = NULL;
742 if (callback == NULL)
743 /* return existing weak reference if it exists */
744 result = ref;
745 if (result != NULL)
746 Py_INCREF(result);
747 else {
748 /* Note: new_weakref() can trigger cyclic GC, so the weakref
749 list on ob can be mutated. This means that the ref and
750 proxy pointers we got back earlier may have been collected,
751 so we need to compute these values again before we use
752 them. */
753 result = new_weakref(ob, callback);
754 if (result != NULL) {
755 get_basic_refs(*list, &ref, &proxy);
756 if (callback == NULL) {
757 if (ref == NULL)
758 insert_head(result, list);
759 else {
760 /* Someone else added a ref without a callback
761 during GC. Return that one instead of this one
762 to avoid violating the invariants of the list
763 of weakrefs for ob. */
764 Py_DECREF(result);
765 Py_INCREF(ref);
766 result = ref;
769 else {
770 PyWeakReference *prev;
772 prev = (proxy == NULL) ? ref : proxy;
773 if (prev == NULL)
774 insert_head(result, list);
775 else
776 insert_after(result, prev);
780 return (PyObject *) result;
784 PyObject *
785 PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
787 PyWeakReference *result = NULL;
788 PyWeakReference **list;
789 PyWeakReference *ref, *proxy;
791 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
792 PyErr_Format(PyExc_TypeError,
793 "cannot create weak reference to '%s' object",
794 Py_TYPE(ob)->tp_name);
795 return NULL;
797 list = GET_WEAKREFS_LISTPTR(ob);
798 get_basic_refs(*list, &ref, &proxy);
799 if (callback == Py_None)
800 callback = NULL;
801 if (callback == NULL)
802 /* attempt to return an existing weak reference if it exists */
803 result = proxy;
804 if (result != NULL)
805 Py_INCREF(result);
806 else {
807 /* Note: new_weakref() can trigger cyclic GC, so the weakref
808 list on ob can be mutated. This means that the ref and
809 proxy pointers we got back earlier may have been collected,
810 so we need to compute these values again before we use
811 them. */
812 result = new_weakref(ob, callback);
813 if (result != NULL) {
814 PyWeakReference *prev;
816 if (PyCallable_Check(ob))
817 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
818 else
819 Py_TYPE(result) = &_PyWeakref_ProxyType;
820 get_basic_refs(*list, &ref, &proxy);
821 if (callback == NULL) {
822 if (proxy != NULL) {
823 /* Someone else added a proxy without a callback
824 during GC. Return that one instead of this one
825 to avoid violating the invariants of the list
826 of weakrefs for ob. */
827 Py_DECREF(result);
828 Py_INCREF(result = proxy);
829 goto skip_insert;
831 prev = ref;
833 else
834 prev = (proxy == NULL) ? ref : proxy;
836 if (prev == NULL)
837 insert_head(result, list);
838 else
839 insert_after(result, prev);
840 skip_insert:
844 return (PyObject *) result;
848 PyObject *
849 PyWeakref_GetObject(PyObject *ref)
851 if (ref == NULL || !PyWeakref_Check(ref)) {
852 PyErr_BadInternalCall();
853 return NULL;
855 return PyWeakref_GET_OBJECT(ref);
858 /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
859 * handle_weakrefs().
861 static void
862 handle_callback(PyWeakReference *ref, PyObject *callback)
864 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
866 if (cbresult == NULL)
867 PyErr_WriteUnraisable(callback);
868 else
869 Py_DECREF(cbresult);
872 /* This function is called by the tp_dealloc handler to clear weak references.
874 * This iterates through the weak references for 'object' and calls callbacks
875 * for those references which have one. It returns when all callbacks have
876 * been attempted.
878 void
879 PyObject_ClearWeakRefs(PyObject *object)
881 PyWeakReference **list;
883 if (object == NULL
884 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
885 || object->ob_refcnt != 0) {
886 PyErr_BadInternalCall();
887 return;
889 list = GET_WEAKREFS_LISTPTR(object);
890 /* Remove the callback-less basic and proxy references */
891 if (*list != NULL && (*list)->wr_callback == NULL) {
892 clear_weakref(*list);
893 if (*list != NULL && (*list)->wr_callback == NULL)
894 clear_weakref(*list);
896 if (*list != NULL) {
897 PyWeakReference *current = *list;
898 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
899 int restore_error = PyErr_Occurred() ? 1 : 0;
900 PyObject *err_type, *err_value, *err_tb;
902 if (restore_error)
903 PyErr_Fetch(&err_type, &err_value, &err_tb);
904 if (count == 1) {
905 PyObject *callback = current->wr_callback;
907 current->wr_callback = NULL;
908 clear_weakref(current);
909 if (callback != NULL) {
910 if (current->ob_refcnt > 0)
911 handle_callback(current, callback);
912 Py_DECREF(callback);
915 else {
916 PyObject *tuple;
917 Py_ssize_t i = 0;
919 tuple = PyTuple_New(count * 2);
920 if (tuple == NULL) {
921 if (restore_error)
922 PyErr_Fetch(&err_type, &err_value, &err_tb);
923 return;
926 for (i = 0; i < count; ++i) {
927 PyWeakReference *next = current->wr_next;
929 if (current->ob_refcnt > 0)
931 Py_INCREF(current);
932 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
933 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
935 else {
936 Py_DECREF(current->wr_callback);
938 current->wr_callback = NULL;
939 clear_weakref(current);
940 current = next;
942 for (i = 0; i < count; ++i) {
943 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
945 /* The tuple may have slots left to NULL */
946 if (callback != NULL) {
947 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
948 handle_callback((PyWeakReference *)item, callback);
951 Py_DECREF(tuple);
953 if (restore_error)
954 PyErr_Restore(err_type, err_value, err_tb);