blob: 2eb4fe0b17fbf043ceba8f6928391bb91e4eeb60 [file] [log] [blame]
Fred Drake8844d522001-10-05 21:52:26 +00001#include "Python.h"
2#include "structmember.h"
3
4
5#define GET_WEAKREFS_LISTPTR(o) \
6 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
7
Fred Drake8844d522001-10-05 21:52:26 +00008
Neal Norwitzc5e060d2006-08-02 06:14:22 +00009Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +000010_PyWeakref_GetWeakrefCount(PyWeakReference *head)
11{
Neal Norwitzc5e060d2006-08-02 06:14:22 +000012 Py_ssize_t count = 0;
Fred Drake8844d522001-10-05 21:52:26 +000013
14 while (head != NULL) {
15 ++count;
16 head = head->wr_next;
17 }
18 return count;
19}
20
21
Fred Drake0a4dd392004-07-02 18:57:45 +000022static void
23init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
24{
25 self->hash = -1;
26 self->wr_object = ob;
Xiang Zhang7131a732017-02-20 14:32:53 +080027 self->wr_prev = NULL;
28 self->wr_next = NULL;
Fred Drake0a4dd392004-07-02 18:57:45 +000029 Py_XINCREF(callback);
30 self->wr_callback = callback;
31}
32
Fred Drake8844d522001-10-05 21:52:26 +000033static PyWeakReference *
Neil Schemenauer38a89162002-03-27 15:18:21 +000034new_weakref(PyObject *ob, PyObject *callback)
Fred Drake8844d522001-10-05 21:52:26 +000035{
36 PyWeakReference *result;
37
Neil Schemenauer38a89162002-03-27 15:18:21 +000038 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
39 if (result) {
Fred Drake0a4dd392004-07-02 18:57:45 +000040 init_weakref(result, ob, callback);
Neil Schemenauer38a89162002-03-27 15:18:21 +000041 PyObject_GC_Track(result);
42 }
Fred Drake8844d522001-10-05 21:52:26 +000043 return result;
44}
45
46
47/* This function clears the passed-in reference and removes it from the
48 * list of weak references for the referent. This is the only code that
49 * removes an item from the doubly-linked list of weak references for an
50 * object; it is also responsible for clearing the callback slot.
51 */
52static void
53clear_weakref(PyWeakReference *self)
54{
55 PyObject *callback = self->wr_callback;
56
Antoine Pitroud38c9902012-12-08 21:15:26 +010057 if (self->wr_object != Py_None) {
58 PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
Fred Drake8844d522001-10-05 21:52:26 +000059
60 if (*list == self)
Antoine Pitrouc83ea132010-05-09 14:46:46 +000061 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
62 then the weakref list itself (and thus the value of *list) will
63 end up being set to NULL. */
Fred Drake8844d522001-10-05 21:52:26 +000064 *list = self->wr_next;
65 self->wr_object = Py_None;
Fred Drake8844d522001-10-05 21:52:26 +000066 if (self->wr_prev != NULL)
67 self->wr_prev->wr_next = self->wr_next;
68 if (self->wr_next != NULL)
69 self->wr_next->wr_prev = self->wr_prev;
70 self->wr_prev = NULL;
71 self->wr_next = NULL;
Tim Peters403a2032003-11-20 21:21:46 +000072 }
73 if (callback != NULL) {
74 Py_DECREF(callback);
75 self->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +000076 }
77}
78
Tim Peters403a2032003-11-20 21:21:46 +000079/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
80 * the callback intact and uncalled. It must be possible to call self's
81 * tp_dealloc() after calling this, so self has to be left in a sane enough
82 * state for that to work. We expect tp_dealloc to decref the callback
83 * then. The reason for not letting clear_weakref() decref the callback
84 * right now is that if the callback goes away, that may in turn trigger
85 * another callback (if a weak reference to the callback exists) -- running
86 * arbitrary Python code in the middle of gc is a disaster. The convolution
87 * here allows gc to delay triggering such callbacks until the world is in
88 * a sane state again.
89 */
90void
91_PyWeakref_ClearRef(PyWeakReference *self)
92{
93 PyObject *callback;
94
95 assert(self != NULL);
96 assert(PyWeakref_Check(self));
97 /* Preserve and restore the callback around clear_weakref. */
98 callback = self->wr_callback;
99 self->wr_callback = NULL;
100 clear_weakref(self);
101 self->wr_callback = callback;
102}
Fred Drake8844d522001-10-05 21:52:26 +0000103
104static void
Fred Drake0a4dd392004-07-02 18:57:45 +0000105weakref_dealloc(PyObject *self)
Fred Drake8844d522001-10-05 21:52:26 +0000106{
Fred Drake0a4dd392004-07-02 18:57:45 +0000107 PyObject_GC_UnTrack(self);
108 clear_weakref((PyWeakReference *) self);
Christian Heimese93237d2007-12-19 02:37:44 +0000109 Py_TYPE(self)->tp_free(self);
Fred Drake8844d522001-10-05 21:52:26 +0000110}
111
112
113static int
114gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
115{
Thomas Woutersc6e55062006-04-15 21:47:09 +0000116 Py_VISIT(self->wr_callback);
Fred Drake8844d522001-10-05 21:52:26 +0000117 return 0;
118}
119
120
121static int
122gc_clear(PyWeakReference *self)
123{
124 clear_weakref(self);
125 return 0;
126}
127
128
129static PyObject *
130weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
131{
Martin v. Löwis15e62742006-02-27 16:46:16 +0000132 static char *kwlist[] = {NULL};
Fred Drake8844d522001-10-05 21:52:26 +0000133
Martin v. Löwis15e62742006-02-27 16:46:16 +0000134 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
Fred Drake8844d522001-10-05 21:52:26 +0000135 PyObject *object = PyWeakref_GET_OBJECT(self);
136 Py_INCREF(object);
137 return (object);
138 }
139 return NULL;
140}
141
142
143static long
144weakref_hash(PyWeakReference *self)
145{
146 if (self->hash != -1)
147 return self->hash;
148 if (PyWeakref_GET_OBJECT(self) == Py_None) {
149 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
150 return -1;
151 }
152 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
153 return self->hash;
154}
Tim Peters403a2032003-11-20 21:21:46 +0000155
Fred Drake8844d522001-10-05 21:52:26 +0000156
157static PyObject *
158weakref_repr(PyWeakReference *self)
159{
160 char buffer[256];
161 if (PyWeakref_GET_OBJECT(self) == Py_None) {
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000162 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
Fred Drake8844d522001-10-05 21:52:26 +0000163 }
164 else {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000165 char *name = NULL;
166 PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
167 "__name__");
168 if (nameobj == NULL)
169 PyErr_Clear();
170 else if (PyString_Check(nameobj))
171 name = PyString_AS_STRING(nameobj);
Gregory P. Smithc0022b22013-02-01 16:13:27 -0800172 if (name != NULL) {
173 PyOS_snprintf(buffer, sizeof(buffer),
174 "<weakref at %p; to '%.50s' at %p (%s)>",
175 self,
176 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
177 PyWeakref_GET_OBJECT(self),
178 name);
179 }
180 else {
181 PyOS_snprintf(buffer, sizeof(buffer),
182 "<weakref at %p; to '%.50s' at %p>",
183 self,
184 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
185 PyWeakref_GET_OBJECT(self));
186 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000187 Py_XDECREF(nameobj);
Fred Drake8844d522001-10-05 21:52:26 +0000188 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000189 return PyString_FromString(buffer);
Fred Drake8844d522001-10-05 21:52:26 +0000190}
191
192/* Weak references only support equality, not ordering. Two weak references
193 are equal if the underlying objects are equal. If the underlying object has
194 gone away, they are equal if they are identical. */
195
196static PyObject *
197weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
198{
Antoine Pitroub704eab2012-11-11 19:36:51 +0100199 if ((op != Py_EQ && op != Py_NE) || self->ob_type != other->ob_type) {
Fred Drake8844d522001-10-05 21:52:26 +0000200 Py_INCREF(Py_NotImplemented);
201 return Py_NotImplemented;
202 }
203 if (PyWeakref_GET_OBJECT(self) == Py_None
204 || PyWeakref_GET_OBJECT(other) == Py_None) {
Antoine Pitroub704eab2012-11-11 19:36:51 +0100205 int res = (self == other);
206 if (op == Py_NE)
207 res = !res;
208 if (res)
209 Py_RETURN_TRUE;
210 else
211 Py_RETURN_FALSE;
Fred Drake8844d522001-10-05 21:52:26 +0000212 }
213 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
214 PyWeakref_GET_OBJECT(other), op);
215}
216
Fred Drake0a4dd392004-07-02 18:57:45 +0000217/* Given the head of an object's list of weak references, extract the
218 * two callback-less refs (ref and proxy). Used to determine if the
219 * shared references exist and to determine the back link for newly
220 * inserted references.
221 */
222static void
223get_basic_refs(PyWeakReference *head,
224 PyWeakReference **refp, PyWeakReference **proxyp)
225{
226 *refp = NULL;
227 *proxyp = NULL;
228
229 if (head != NULL && head->wr_callback == NULL) {
230 /* We need to be careful that the "basic refs" aren't
231 subclasses of the main types. That complicates this a
232 little. */
233 if (PyWeakref_CheckRefExact(head)) {
234 *refp = head;
235 head = head->wr_next;
236 }
237 if (head != NULL
238 && head->wr_callback == NULL
239 && PyWeakref_CheckProxy(head)) {
240 *proxyp = head;
241 /* head = head->wr_next; */
242 }
243 }
244}
245
246/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
247static void
248insert_after(PyWeakReference *newref, PyWeakReference *prev)
249{
250 newref->wr_prev = prev;
251 newref->wr_next = prev->wr_next;
252 if (prev->wr_next != NULL)
253 prev->wr_next->wr_prev = newref;
254 prev->wr_next = newref;
255}
256
257/* Insert 'newref' at the head of the list; 'list' points to the variable
258 * that stores the head.
259 */
260static void
261insert_head(PyWeakReference *newref, PyWeakReference **list)
262{
263 PyWeakReference *next = *list;
264
265 newref->wr_prev = NULL;
266 newref->wr_next = next;
267 if (next != NULL)
268 next->wr_prev = newref;
269 *list = newref;
270}
271
272static int
273parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
274 PyObject **obp, PyObject **callbackp)
275{
Fred Drake0a4dd392004-07-02 18:57:45 +0000276 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
277}
278
279static PyObject *
280weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
281{
282 PyWeakReference *self = NULL;
283 PyObject *ob, *callback = NULL;
284
285 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
286 PyWeakReference *ref, *proxy;
287 PyWeakReference **list;
288
Christian Heimese93237d2007-12-19 02:37:44 +0000289 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000290 PyErr_Format(PyExc_TypeError,
291 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000292 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000293 return NULL;
294 }
295 if (callback == Py_None)
296 callback = NULL;
297 list = GET_WEAKREFS_LISTPTR(ob);
298 get_basic_refs(*list, &ref, &proxy);
299 if (callback == NULL && type == &_PyWeakref_RefType) {
300 if (ref != NULL) {
301 /* We can re-use an existing reference. */
302 Py_INCREF(ref);
303 return (PyObject *)ref;
304 }
305 }
306 /* We have to create a new reference. */
307 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
308 list on ob can be mutated. This means that the ref and
309 proxy pointers we got back earlier may have been collected,
310 so we need to compute these values again before we use
311 them. */
312 self = (PyWeakReference *) (type->tp_alloc(type, 0));
313 if (self != NULL) {
314 init_weakref(self, ob, callback);
315 if (callback == NULL && type == &_PyWeakref_RefType) {
316 insert_head(self, list);
317 }
318 else {
319 PyWeakReference *prev;
320
321 get_basic_refs(*list, &ref, &proxy);
322 prev = (proxy == NULL) ? ref : proxy;
323 if (prev == NULL)
324 insert_head(self, list);
325 else
326 insert_after(self, prev);
327 }
328 }
329 }
330 return (PyObject *)self;
331}
332
333static int
334weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
335{
336 PyObject *tmp;
337
Serhiy Storchaka816a5ff2016-05-07 15:41:09 +0300338 if (!_PyArg_NoKeywords("ref()", kwargs))
339 return -1;
340
Fred Drake0a4dd392004-07-02 18:57:45 +0000341 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
342 return 0;
343 else
Benjamin Peterson97179b02008-09-09 20:55:01 +0000344 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000345}
346
Fred Drake8844d522001-10-05 21:52:26 +0000347
348PyTypeObject
349_PyWeakref_RefType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000350 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000351 "weakref",
352 sizeof(PyWeakReference),
353 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000354 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000355 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000356 0, /*tp_getattr*/
357 0, /*tp_setattr*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000358 0, /*tp_compare*/
Fred Drake8844d522001-10-05 21:52:26 +0000359 (reprfunc)weakref_repr, /*tp_repr*/
360 0, /*tp_as_number*/
361 0, /*tp_as_sequence*/
362 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000363 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000364 (ternaryfunc)weakref_call, /*tp_call*/
365 0, /*tp_str*/
366 0, /*tp_getattro*/
367 0, /*tp_setattro*/
368 0, /*tp_as_buffer*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000369 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
370 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000371 0, /*tp_doc*/
372 (traverseproc)gc_traverse, /*tp_traverse*/
373 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000374 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000375 0, /*tp_weaklistoffset*/
376 0, /*tp_iter*/
377 0, /*tp_iternext*/
378 0, /*tp_methods*/
379 0, /*tp_members*/
380 0, /*tp_getset*/
381 0, /*tp_base*/
382 0, /*tp_dict*/
383 0, /*tp_descr_get*/
384 0, /*tp_descr_set*/
385 0, /*tp_dictoffset*/
Georg Brandl347b3002006-03-30 11:57:00 +0000386 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000387 PyType_GenericAlloc, /*tp_alloc*/
388 weakref___new__, /*tp_new*/
389 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000390};
391
392
393static int
394proxy_checkref(PyWeakReference *proxy)
395{
396 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
397 PyErr_SetString(PyExc_ReferenceError,
398 "weakly-referenced object no longer exists");
399 return 0;
400 }
401 return 1;
402}
403
404
Fred Drake73006d02001-10-18 18:04:18 +0000405/* If a parameter is a proxy, check that it is still "live" and wrap it,
406 * replacing the original value with the raw object. Raises ReferenceError
407 * if the param is a dead proxy.
408 */
409#define UNWRAP(o) \
410 if (PyWeakref_CheckProxy(o)) { \
411 if (!proxy_checkref((PyWeakReference *)o)) \
412 return NULL; \
413 o = PyWeakref_GET_OBJECT(o); \
414 }
415
Fred Drake2a908f62001-12-19 16:44:30 +0000416#define UNWRAP_I(o) \
417 if (PyWeakref_CheckProxy(o)) { \
418 if (!proxy_checkref((PyWeakReference *)o)) \
419 return -1; \
420 o = PyWeakref_GET_OBJECT(o); \
421 }
422
Fred Drake8844d522001-10-05 21:52:26 +0000423#define WRAP_UNARY(method, generic) \
424 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000425 method(PyObject *proxy) { \
426 UNWRAP(proxy); \
427 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000428 }
429
430#define WRAP_BINARY(method, generic) \
431 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000432 method(PyObject *x, PyObject *y) { \
433 UNWRAP(x); \
434 UNWRAP(y); \
435 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000436 }
437
Fred Drake31f4d1f2001-10-18 19:21:46 +0000438/* Note that the third arg needs to be checked for NULL since the tp_call
439 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000440 */
Fred Drake8844d522001-10-05 21:52:26 +0000441#define WRAP_TERNARY(method, generic) \
442 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000443 method(PyObject *proxy, PyObject *v, PyObject *w) { \
444 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000445 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000446 if (w != NULL) \
447 UNWRAP(w); \
448 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000449 }
450
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000451#define WRAP_METHOD(method, special) \
452 static PyObject * \
453 method(PyObject *proxy) { \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000454 UNWRAP(proxy); \
455 return PyObject_CallMethod(proxy, special, ""); \
456 }
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000457
Fred Drake8844d522001-10-05 21:52:26 +0000458
459/* direct slots */
460
461WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
462WRAP_UNARY(proxy_str, PyObject_Str)
463WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
464
Fred Drake8844d522001-10-05 21:52:26 +0000465static PyObject *
466proxy_repr(PyWeakReference *proxy)
467{
468 char buf[160];
Barry Warsawd5867562001-11-28 21:01:56 +0000469 PyOS_snprintf(buf, sizeof(buf),
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000470 "<weakproxy at %p to %.100s at %p>", proxy,
471 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
472 PyWeakref_GET_OBJECT(proxy));
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000473 return PyString_FromString(buf);
Fred Drake8844d522001-10-05 21:52:26 +0000474}
475
476
477static int
478proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
479{
480 if (!proxy_checkref(proxy))
481 return -1;
482 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
483}
484
485static int
Fred Drake2a908f62001-12-19 16:44:30 +0000486proxy_compare(PyObject *proxy, PyObject *v)
Fred Drake8844d522001-10-05 21:52:26 +0000487{
Fred Drake2a908f62001-12-19 16:44:30 +0000488 UNWRAP_I(proxy);
489 UNWRAP_I(v);
490 return PyObject_Compare(proxy, v);
Fred Drake8844d522001-10-05 21:52:26 +0000491}
492
493/* number slots */
494WRAP_BINARY(proxy_add, PyNumber_Add)
495WRAP_BINARY(proxy_sub, PyNumber_Subtract)
496WRAP_BINARY(proxy_mul, PyNumber_Multiply)
497WRAP_BINARY(proxy_div, PyNumber_Divide)
Georg Brandl88659b02008-05-20 08:40:43 +0000498WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
499WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000500WRAP_BINARY(proxy_mod, PyNumber_Remainder)
501WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
502WRAP_TERNARY(proxy_pow, PyNumber_Power)
503WRAP_UNARY(proxy_neg, PyNumber_Negative)
504WRAP_UNARY(proxy_pos, PyNumber_Positive)
505WRAP_UNARY(proxy_abs, PyNumber_Absolute)
506WRAP_UNARY(proxy_invert, PyNumber_Invert)
507WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
508WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
509WRAP_BINARY(proxy_and, PyNumber_And)
510WRAP_BINARY(proxy_xor, PyNumber_Xor)
511WRAP_BINARY(proxy_or, PyNumber_Or)
512WRAP_UNARY(proxy_int, PyNumber_Int)
513WRAP_UNARY(proxy_long, PyNumber_Long)
514WRAP_UNARY(proxy_float, PyNumber_Float)
515WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
516WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
517WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
518WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
Georg Brandl88659b02008-05-20 08:40:43 +0000519WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
520WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000521WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
522WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
523WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
524WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
525WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
526WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
527WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandl88659b02008-05-20 08:40:43 +0000528WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000529
Tim Peters403a2032003-11-20 21:21:46 +0000530static int
Fred Drake8844d522001-10-05 21:52:26 +0000531proxy_nonzero(PyWeakReference *proxy)
532{
533 PyObject *o = PyWeakref_GET_OBJECT(proxy);
534 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000535 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000536 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000537}
538
Fred Drake0a4dd392004-07-02 18:57:45 +0000539static void
540proxy_dealloc(PyWeakReference *self)
541{
542 if (self->wr_callback != NULL)
543 PyObject_GC_UnTrack((PyObject *)self);
544 clear_weakref(self);
545 PyObject_GC_Del(self);
546}
547
Fred Drake8844d522001-10-05 21:52:26 +0000548/* sequence slots */
549
550static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000551proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
Fred Drake8844d522001-10-05 21:52:26 +0000552{
553 if (!proxy_checkref(proxy))
554 return NULL;
555 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
556}
557
558static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000559proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
Fred Drake8844d522001-10-05 21:52:26 +0000560{
561 if (!proxy_checkref(proxy))
562 return -1;
563 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
564}
565
566static int
567proxy_contains(PyWeakReference *proxy, PyObject *value)
568{
569 if (!proxy_checkref(proxy))
570 return -1;
571 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
572}
573
574
575/* mapping slots */
576
Martin v. Löwis18e16552006-02-15 17:27:45 +0000577static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000578proxy_length(PyWeakReference *proxy)
579{
580 if (!proxy_checkref(proxy))
581 return -1;
582 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
583}
584
585WRAP_BINARY(proxy_getitem, PyObject_GetItem)
586
587static int
588proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
589{
590 if (!proxy_checkref(proxy))
591 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000592
593 if (value == NULL)
594 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
595 else
596 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000597}
598
Fred Drakef16c3dc2002-08-09 18:34:16 +0000599/* iterator slots */
600
601static PyObject *
602proxy_iter(PyWeakReference *proxy)
603{
604 if (!proxy_checkref(proxy))
605 return NULL;
606 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
607}
608
609static PyObject *
610proxy_iternext(PyWeakReference *proxy)
611{
612 if (!proxy_checkref(proxy))
613 return NULL;
614 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
615}
616
Fred Drake8844d522001-10-05 21:52:26 +0000617
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000618WRAP_METHOD(proxy_unicode, "__unicode__");
619
620
621static PyMethodDef proxy_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000622 {"__unicode__", (PyCFunction)proxy_unicode, METH_NOARGS},
623 {NULL, NULL}
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000624};
625
626
Fred Drake8844d522001-10-05 21:52:26 +0000627static PyNumberMethods proxy_as_number = {
Georg Brandl347b3002006-03-30 11:57:00 +0000628 proxy_add, /*nb_add*/
629 proxy_sub, /*nb_subtract*/
630 proxy_mul, /*nb_multiply*/
631 proxy_div, /*nb_divide*/
632 proxy_mod, /*nb_remainder*/
633 proxy_divmod, /*nb_divmod*/
634 proxy_pow, /*nb_power*/
635 proxy_neg, /*nb_negative*/
636 proxy_pos, /*nb_positive*/
637 proxy_abs, /*nb_absolute*/
638 (inquiry)proxy_nonzero, /*nb_nonzero*/
639 proxy_invert, /*nb_invert*/
640 proxy_lshift, /*nb_lshift*/
641 proxy_rshift, /*nb_rshift*/
642 proxy_and, /*nb_and*/
643 proxy_xor, /*nb_xor*/
644 proxy_or, /*nb_or*/
645 0, /*nb_coerce*/
646 proxy_int, /*nb_int*/
647 proxy_long, /*nb_long*/
648 proxy_float, /*nb_float*/
649 0, /*nb_oct*/
650 0, /*nb_hex*/
651 proxy_iadd, /*nb_inplace_add*/
652 proxy_isub, /*nb_inplace_subtract*/
653 proxy_imul, /*nb_inplace_multiply*/
654 proxy_idiv, /*nb_inplace_divide*/
655 proxy_imod, /*nb_inplace_remainder*/
656 proxy_ipow, /*nb_inplace_power*/
657 proxy_ilshift, /*nb_inplace_lshift*/
658 proxy_irshift, /*nb_inplace_rshift*/
659 proxy_iand, /*nb_inplace_and*/
660 proxy_ixor, /*nb_inplace_xor*/
661 proxy_ior, /*nb_inplace_or*/
Georg Brandl88659b02008-05-20 08:40:43 +0000662 proxy_floor_div, /*nb_floor_divide*/
663 proxy_true_div, /*nb_true_divide*/
664 proxy_ifloor_div, /*nb_inplace_floor_divide*/
665 proxy_itrue_div, /*nb_inplace_true_divide*/
666 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000667};
668
669static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000670 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000671 0, /*sq_concat*/
672 0, /*sq_repeat*/
673 0, /*sq_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000674 (ssizessizeargfunc)proxy_slice, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000675 0, /*sq_ass_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000676 (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000677 (objobjproc)proxy_contains, /* sq_contains */
678};
679
680static PyMappingMethods proxy_as_mapping = {
Georg Brandl347b3002006-03-30 11:57:00 +0000681 (lenfunc)proxy_length, /*mp_length*/
682 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000683 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
684};
685
686
687PyTypeObject
688_PyWeakref_ProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000689 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000690 "weakproxy",
691 sizeof(PyWeakReference),
692 0,
693 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000694 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000695 0, /* tp_print */
696 0, /* tp_getattr */
697 0, /* tp_setattr */
698 proxy_compare, /* tp_compare */
699 (reprfunc)proxy_repr, /* tp_repr */
700 &proxy_as_number, /* tp_as_number */
701 &proxy_as_sequence, /* tp_as_sequence */
702 &proxy_as_mapping, /* tp_as_mapping */
703 0, /* tp_hash */
704 0, /* tp_call */
Georg Brandl347b3002006-03-30 11:57:00 +0000705 proxy_str, /* tp_str */
706 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000707 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000708 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000709 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000710 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
711 0, /* tp_doc */
712 (traverseproc)gc_traverse, /* tp_traverse */
713 (inquiry)gc_clear, /* tp_clear */
714 0, /* tp_richcompare */
715 0, /* tp_weaklistoffset */
716 (getiterfunc)proxy_iter, /* tp_iter */
717 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000718 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000719};
720
721
722PyTypeObject
723_PyWeakref_CallableProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000724 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000725 "weakcallableproxy",
726 sizeof(PyWeakReference),
727 0,
728 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000729 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000730 0, /* tp_print */
731 0, /* tp_getattr */
732 0, /* tp_setattr */
733 proxy_compare, /* tp_compare */
734 (unaryfunc)proxy_repr, /* tp_repr */
735 &proxy_as_number, /* tp_as_number */
736 &proxy_as_sequence, /* tp_as_sequence */
737 &proxy_as_mapping, /* tp_as_mapping */
738 0, /* tp_hash */
739 proxy_call, /* tp_call */
740 proxy_str, /* tp_str */
Georg Brandl347b3002006-03-30 11:57:00 +0000741 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000742 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000743 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000744 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000745 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
746 0, /* tp_doc */
747 (traverseproc)gc_traverse, /* tp_traverse */
748 (inquiry)gc_clear, /* tp_clear */
749 0, /* tp_richcompare */
750 0, /* tp_weaklistoffset */
751 (getiterfunc)proxy_iter, /* tp_iter */
752 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000753};
754
755
Fred Drake8844d522001-10-05 21:52:26 +0000756
757PyObject *
758PyWeakref_NewRef(PyObject *ob, PyObject *callback)
759{
760 PyWeakReference *result = NULL;
761 PyWeakReference **list;
762 PyWeakReference *ref, *proxy;
763
Christian Heimese93237d2007-12-19 02:37:44 +0000764 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000765 PyErr_Format(PyExc_TypeError,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000766 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000767 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000768 return NULL;
769 }
770 list = GET_WEAKREFS_LISTPTR(ob);
771 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000772 if (callback == Py_None)
773 callback = NULL;
774 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000775 /* return existing weak reference if it exists */
776 result = ref;
777 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000778 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000779 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000780 /* Note: new_weakref() can trigger cyclic GC, so the weakref
781 list on ob can be mutated. This means that the ref and
782 proxy pointers we got back earlier may have been collected,
783 so we need to compute these values again before we use
784 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000785 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000786 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000787 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000788 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000789 if (ref == NULL)
790 insert_head(result, list);
791 else {
792 /* Someone else added a ref without a callback
793 during GC. Return that one instead of this one
794 to avoid violating the invariants of the list
795 of weakrefs for ob. */
796 Py_DECREF(result);
797 Py_INCREF(ref);
798 result = ref;
799 }
Fred Drake8844d522001-10-05 21:52:26 +0000800 }
801 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000802 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000803
Fred Drakebc875f52004-02-04 23:14:14 +0000804 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000805 if (prev == NULL)
806 insert_head(result, list);
807 else
808 insert_after(result, prev);
809 }
Fred Drake8844d522001-10-05 21:52:26 +0000810 }
811 }
812 return (PyObject *) result;
813}
814
815
816PyObject *
817PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
818{
819 PyWeakReference *result = NULL;
820 PyWeakReference **list;
821 PyWeakReference *ref, *proxy;
822
Christian Heimese93237d2007-12-19 02:37:44 +0000823 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000824 PyErr_Format(PyExc_TypeError,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000825 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000826 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000827 return NULL;
828 }
829 list = GET_WEAKREFS_LISTPTR(ob);
830 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000831 if (callback == Py_None)
832 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000833 if (callback == NULL)
834 /* attempt to return an existing weak reference if it exists */
835 result = proxy;
836 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000837 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000838 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000839 /* Note: new_weakref() can trigger cyclic GC, so the weakref
840 list on ob can be mutated. This means that the ref and
841 proxy pointers we got back earlier may have been collected,
842 so we need to compute these values again before we use
843 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000844 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000845 if (result != NULL) {
846 PyWeakReference *prev;
847
848 if (PyCallable_Check(ob))
Christian Heimese93237d2007-12-19 02:37:44 +0000849 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000850 else
Christian Heimese93237d2007-12-19 02:37:44 +0000851 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000852 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000853 if (callback == NULL) {
854 if (proxy != NULL) {
855 /* Someone else added a proxy without a callback
856 during GC. Return that one instead of this one
857 to avoid violating the invariants of the list
858 of weakrefs for ob. */
859 Py_DECREF(result);
860 Py_INCREF(result = proxy);
861 goto skip_insert;
862 }
Fred Drake8844d522001-10-05 21:52:26 +0000863 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000864 }
Fred Drake8844d522001-10-05 21:52:26 +0000865 else
866 prev = (proxy == NULL) ? ref : proxy;
867
868 if (prev == NULL)
869 insert_head(result, list);
870 else
871 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000872 skip_insert:
873 ;
Fred Drake8844d522001-10-05 21:52:26 +0000874 }
875 }
876 return (PyObject *) result;
877}
878
879
880PyObject *
881PyWeakref_GetObject(PyObject *ref)
882{
883 if (ref == NULL || !PyWeakref_Check(ref)) {
884 PyErr_BadInternalCall();
885 return NULL;
886 }
887 return PyWeakref_GET_OBJECT(ref);
888}
889
Tim Petersead8b7a2004-10-30 23:09:22 +0000890/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
891 * handle_weakrefs().
892 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000893static void
894handle_callback(PyWeakReference *ref, PyObject *callback)
895{
Georg Brandl684fd0c2006-05-25 19:15:31 +0000896 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000897
898 if (cbresult == NULL)
899 PyErr_WriteUnraisable(callback);
900 else
901 Py_DECREF(cbresult);
902}
903
904/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000905 *
906 * This iterates through the weak references for 'object' and calls callbacks
907 * for those references which have one. It returns when all callbacks have
908 * been attempted.
909 */
910void
911PyObject_ClearWeakRefs(PyObject *object)
912{
913 PyWeakReference **list;
914
915 if (object == NULL
Christian Heimese93237d2007-12-19 02:37:44 +0000916 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000917 || object->ob_refcnt != 0) {
918 PyErr_BadInternalCall();
919 return;
920 }
921 list = GET_WEAKREFS_LISTPTR(object);
922 /* Remove the callback-less basic and proxy references */
923 if (*list != NULL && (*list)->wr_callback == NULL) {
924 clear_weakref(*list);
925 if (*list != NULL && (*list)->wr_callback == NULL)
926 clear_weakref(*list);
927 }
928 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000929 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000930 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000931 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000932
Serhiy Storchaka07e03ab2015-03-30 09:53:06 +0300933 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000934 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000935 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000936
Fred Drakeef8ebd12001-12-10 23:44:54 +0000937 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000938 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000939 if (callback != NULL) {
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000940 if (current->ob_refcnt > 0)
941 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000942 Py_DECREF(callback);
943 }
Fred Drake8844d522001-10-05 21:52:26 +0000944 }
945 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000946 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000947 Py_ssize_t i = 0;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000948
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000949 tuple = PyTuple_New(count * 2);
950 if (tuple == NULL) {
Serhiy Storchaka07e03ab2015-03-30 09:53:06 +0300951 _PyErr_ReplaceException(err_type, err_value, err_tb);
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000952 return;
953 }
Fred Drake8844d522001-10-05 21:52:26 +0000954
955 for (i = 0; i < count; ++i) {
956 PyWeakReference *next = current->wr_next;
957
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000958 if (current->ob_refcnt > 0)
959 {
960 Py_INCREF(current);
961 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
962 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
963 }
964 else {
965 Py_DECREF(current->wr_callback);
966 }
Fred Drake8844d522001-10-05 21:52:26 +0000967 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000968 clear_weakref(current);
969 current = next;
970 }
971 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000972 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000973
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000974 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000975 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000976 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
977 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000978 }
Fred Drake8844d522001-10-05 21:52:26 +0000979 }
980 Py_DECREF(tuple);
981 }
Serhiy Storchaka07e03ab2015-03-30 09:53:06 +0300982 assert(!PyErr_Occurred());
983 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000984 }
985}