blob: c8b982fcd59ce823b3f9bc0e81e707fd58c1a014 [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;
27 Py_XINCREF(callback);
28 self->wr_callback = callback;
29}
30
Fred Drake8844d522001-10-05 21:52:26 +000031static PyWeakReference *
Neil Schemenauer38a89162002-03-27 15:18:21 +000032new_weakref(PyObject *ob, PyObject *callback)
Fred Drake8844d522001-10-05 21:52:26 +000033{
34 PyWeakReference *result;
35
Neil Schemenauer38a89162002-03-27 15:18:21 +000036 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
37 if (result) {
Fred Drake0a4dd392004-07-02 18:57:45 +000038 init_weakref(result, ob, callback);
Neil Schemenauer38a89162002-03-27 15:18:21 +000039 PyObject_GC_Track(result);
40 }
Fred Drake8844d522001-10-05 21:52:26 +000041 return result;
42}
43
44
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.
49 */
50static void
51clear_weakref(PyWeakReference *self)
52{
53 PyObject *callback = self->wr_callback;
54
Antoine Pitroud38c9902012-12-08 21:15:26 +010055 if (self->wr_object != Py_None) {
56 PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
Fred Drake8844d522001-10-05 21:52:26 +000057
58 if (*list == self)
Antoine Pitrouc83ea132010-05-09 14:46:46 +000059 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
60 then the weakref list itself (and thus the value of *list) will
61 end up being set to NULL. */
Fred Drake8844d522001-10-05 21:52:26 +000062 *list = self->wr_next;
63 self->wr_object = Py_None;
Fred Drake8844d522001-10-05 21:52:26 +000064 if (self->wr_prev != NULL)
65 self->wr_prev->wr_next = self->wr_next;
66 if (self->wr_next != NULL)
67 self->wr_next->wr_prev = self->wr_prev;
68 self->wr_prev = NULL;
69 self->wr_next = NULL;
Tim Peters403a2032003-11-20 21:21:46 +000070 }
71 if (callback != NULL) {
72 Py_DECREF(callback);
73 self->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +000074 }
75}
76
Tim Peters403a2032003-11-20 21:21:46 +000077/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
78 * the callback intact and uncalled. It must be possible to call self's
79 * tp_dealloc() after calling this, so self has to be left in a sane enough
80 * state for that to work. We expect tp_dealloc to decref the callback
81 * then. The reason for not letting clear_weakref() decref the callback
82 * right now is that if the callback goes away, that may in turn trigger
83 * another callback (if a weak reference to the callback exists) -- running
84 * arbitrary Python code in the middle of gc is a disaster. The convolution
85 * here allows gc to delay triggering such callbacks until the world is in
86 * a sane state again.
87 */
88void
89_PyWeakref_ClearRef(PyWeakReference *self)
90{
91 PyObject *callback;
92
93 assert(self != NULL);
94 assert(PyWeakref_Check(self));
95 /* Preserve and restore the callback around clear_weakref. */
96 callback = self->wr_callback;
97 self->wr_callback = NULL;
98 clear_weakref(self);
99 self->wr_callback = callback;
100}
Fred Drake8844d522001-10-05 21:52:26 +0000101
102static void
Fred Drake0a4dd392004-07-02 18:57:45 +0000103weakref_dealloc(PyObject *self)
Fred Drake8844d522001-10-05 21:52:26 +0000104{
Fred Drake0a4dd392004-07-02 18:57:45 +0000105 PyObject_GC_UnTrack(self);
106 clear_weakref((PyWeakReference *) self);
Christian Heimese93237d2007-12-19 02:37:44 +0000107 Py_TYPE(self)->tp_free(self);
Fred Drake8844d522001-10-05 21:52:26 +0000108}
109
110
111static int
112gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
113{
Thomas Woutersc6e55062006-04-15 21:47:09 +0000114 Py_VISIT(self->wr_callback);
Fred Drake8844d522001-10-05 21:52:26 +0000115 return 0;
116}
117
118
119static int
120gc_clear(PyWeakReference *self)
121{
122 clear_weakref(self);
123 return 0;
124}
125
126
127static PyObject *
128weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
129{
Martin v. Löwis15e62742006-02-27 16:46:16 +0000130 static char *kwlist[] = {NULL};
Fred Drake8844d522001-10-05 21:52:26 +0000131
Martin v. Löwis15e62742006-02-27 16:46:16 +0000132 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
Fred Drake8844d522001-10-05 21:52:26 +0000133 PyObject *object = PyWeakref_GET_OBJECT(self);
134 Py_INCREF(object);
135 return (object);
136 }
137 return NULL;
138}
139
140
141static long
142weakref_hash(PyWeakReference *self)
143{
144 if (self->hash != -1)
145 return self->hash;
146 if (PyWeakref_GET_OBJECT(self) == Py_None) {
147 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
148 return -1;
149 }
150 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
151 return self->hash;
152}
Tim Peters403a2032003-11-20 21:21:46 +0000153
Fred Drake8844d522001-10-05 21:52:26 +0000154
155static PyObject *
156weakref_repr(PyWeakReference *self)
157{
158 char buffer[256];
159 if (PyWeakref_GET_OBJECT(self) == Py_None) {
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000160 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
Fred Drake8844d522001-10-05 21:52:26 +0000161 }
162 else {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000163 char *name = NULL;
164 PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
165 "__name__");
166 if (nameobj == NULL)
167 PyErr_Clear();
168 else if (PyString_Check(nameobj))
169 name = PyString_AS_STRING(nameobj);
Gregory P. Smithc0022b22013-02-01 16:13:27 -0800170 if (name != NULL) {
171 PyOS_snprintf(buffer, sizeof(buffer),
172 "<weakref at %p; to '%.50s' at %p (%s)>",
173 self,
174 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
175 PyWeakref_GET_OBJECT(self),
176 name);
177 }
178 else {
179 PyOS_snprintf(buffer, sizeof(buffer),
180 "<weakref at %p; to '%.50s' at %p>",
181 self,
182 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
183 PyWeakref_GET_OBJECT(self));
184 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000185 Py_XDECREF(nameobj);
Fred Drake8844d522001-10-05 21:52:26 +0000186 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000187 return PyString_FromString(buffer);
Fred Drake8844d522001-10-05 21:52:26 +0000188}
189
190/* Weak references only support equality, not ordering. Two weak references
191 are equal if the underlying objects are equal. If the underlying object has
192 gone away, they are equal if they are identical. */
193
194static PyObject *
195weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
196{
Antoine Pitroub704eab2012-11-11 19:36:51 +0100197 if ((op != Py_EQ && op != Py_NE) || self->ob_type != other->ob_type) {
Fred Drake8844d522001-10-05 21:52:26 +0000198 Py_INCREF(Py_NotImplemented);
199 return Py_NotImplemented;
200 }
201 if (PyWeakref_GET_OBJECT(self) == Py_None
202 || PyWeakref_GET_OBJECT(other) == Py_None) {
Antoine Pitroub704eab2012-11-11 19:36:51 +0100203 int res = (self == other);
204 if (op == Py_NE)
205 res = !res;
206 if (res)
207 Py_RETURN_TRUE;
208 else
209 Py_RETURN_FALSE;
Fred Drake8844d522001-10-05 21:52:26 +0000210 }
211 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
212 PyWeakref_GET_OBJECT(other), op);
213}
214
Fred Drake0a4dd392004-07-02 18:57:45 +0000215/* Given the head of an object's list of weak references, extract the
216 * two callback-less refs (ref and proxy). Used to determine if the
217 * shared references exist and to determine the back link for newly
218 * inserted references.
219 */
220static void
221get_basic_refs(PyWeakReference *head,
222 PyWeakReference **refp, PyWeakReference **proxyp)
223{
224 *refp = NULL;
225 *proxyp = NULL;
226
227 if (head != NULL && head->wr_callback == NULL) {
228 /* We need to be careful that the "basic refs" aren't
229 subclasses of the main types. That complicates this a
230 little. */
231 if (PyWeakref_CheckRefExact(head)) {
232 *refp = head;
233 head = head->wr_next;
234 }
235 if (head != NULL
236 && head->wr_callback == NULL
237 && PyWeakref_CheckProxy(head)) {
238 *proxyp = head;
239 /* head = head->wr_next; */
240 }
241 }
242}
243
244/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
245static void
246insert_after(PyWeakReference *newref, PyWeakReference *prev)
247{
248 newref->wr_prev = prev;
249 newref->wr_next = prev->wr_next;
250 if (prev->wr_next != NULL)
251 prev->wr_next->wr_prev = newref;
252 prev->wr_next = newref;
253}
254
255/* Insert 'newref' at the head of the list; 'list' points to the variable
256 * that stores the head.
257 */
258static void
259insert_head(PyWeakReference *newref, PyWeakReference **list)
260{
261 PyWeakReference *next = *list;
262
263 newref->wr_prev = NULL;
264 newref->wr_next = next;
265 if (next != NULL)
266 next->wr_prev = newref;
267 *list = newref;
268}
269
270static int
271parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
272 PyObject **obp, PyObject **callbackp)
273{
Fred Drake0a4dd392004-07-02 18:57:45 +0000274 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
275}
276
277static PyObject *
278weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
279{
280 PyWeakReference *self = NULL;
281 PyObject *ob, *callback = NULL;
282
283 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
284 PyWeakReference *ref, *proxy;
285 PyWeakReference **list;
286
Christian Heimese93237d2007-12-19 02:37:44 +0000287 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000288 PyErr_Format(PyExc_TypeError,
289 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000290 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000291 return NULL;
292 }
293 if (callback == Py_None)
294 callback = NULL;
295 list = GET_WEAKREFS_LISTPTR(ob);
296 get_basic_refs(*list, &ref, &proxy);
297 if (callback == NULL && type == &_PyWeakref_RefType) {
298 if (ref != NULL) {
299 /* We can re-use an existing reference. */
300 Py_INCREF(ref);
301 return (PyObject *)ref;
302 }
303 }
304 /* We have to create a new reference. */
305 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
306 list on ob can be mutated. This means that the ref and
307 proxy pointers we got back earlier may have been collected,
308 so we need to compute these values again before we use
309 them. */
310 self = (PyWeakReference *) (type->tp_alloc(type, 0));
311 if (self != NULL) {
312 init_weakref(self, ob, callback);
313 if (callback == NULL && type == &_PyWeakref_RefType) {
314 insert_head(self, list);
315 }
316 else {
317 PyWeakReference *prev;
318
319 get_basic_refs(*list, &ref, &proxy);
320 prev = (proxy == NULL) ? ref : proxy;
321 if (prev == NULL)
322 insert_head(self, list);
323 else
324 insert_after(self, prev);
325 }
326 }
327 }
328 return (PyObject *)self;
329}
330
331static int
332weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
333{
334 PyObject *tmp;
335
Serhiy Storchaka816a5ff2016-05-07 15:41:09 +0300336 if (!_PyArg_NoKeywords("ref()", kwargs))
337 return -1;
338
Fred Drake0a4dd392004-07-02 18:57:45 +0000339 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
340 return 0;
341 else
Benjamin Peterson97179b02008-09-09 20:55:01 +0000342 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000343}
344
Fred Drake8844d522001-10-05 21:52:26 +0000345
346PyTypeObject
347_PyWeakref_RefType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000348 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000349 "weakref",
350 sizeof(PyWeakReference),
351 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000352 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000353 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000354 0, /*tp_getattr*/
355 0, /*tp_setattr*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000356 0, /*tp_compare*/
Fred Drake8844d522001-10-05 21:52:26 +0000357 (reprfunc)weakref_repr, /*tp_repr*/
358 0, /*tp_as_number*/
359 0, /*tp_as_sequence*/
360 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000361 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000362 (ternaryfunc)weakref_call, /*tp_call*/
363 0, /*tp_str*/
364 0, /*tp_getattro*/
365 0, /*tp_setattro*/
366 0, /*tp_as_buffer*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000367 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
368 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000369 0, /*tp_doc*/
370 (traverseproc)gc_traverse, /*tp_traverse*/
371 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000372 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000373 0, /*tp_weaklistoffset*/
374 0, /*tp_iter*/
375 0, /*tp_iternext*/
376 0, /*tp_methods*/
377 0, /*tp_members*/
378 0, /*tp_getset*/
379 0, /*tp_base*/
380 0, /*tp_dict*/
381 0, /*tp_descr_get*/
382 0, /*tp_descr_set*/
383 0, /*tp_dictoffset*/
Georg Brandl347b3002006-03-30 11:57:00 +0000384 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000385 PyType_GenericAlloc, /*tp_alloc*/
386 weakref___new__, /*tp_new*/
387 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000388};
389
390
391static int
392proxy_checkref(PyWeakReference *proxy)
393{
394 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
395 PyErr_SetString(PyExc_ReferenceError,
396 "weakly-referenced object no longer exists");
397 return 0;
398 }
399 return 1;
400}
401
402
Fred Drake73006d02001-10-18 18:04:18 +0000403/* If a parameter is a proxy, check that it is still "live" and wrap it,
404 * replacing the original value with the raw object. Raises ReferenceError
405 * if the param is a dead proxy.
406 */
407#define UNWRAP(o) \
408 if (PyWeakref_CheckProxy(o)) { \
409 if (!proxy_checkref((PyWeakReference *)o)) \
410 return NULL; \
411 o = PyWeakref_GET_OBJECT(o); \
412 }
413
Fred Drake2a908f62001-12-19 16:44:30 +0000414#define UNWRAP_I(o) \
415 if (PyWeakref_CheckProxy(o)) { \
416 if (!proxy_checkref((PyWeakReference *)o)) \
417 return -1; \
418 o = PyWeakref_GET_OBJECT(o); \
419 }
420
Fred Drake8844d522001-10-05 21:52:26 +0000421#define WRAP_UNARY(method, generic) \
422 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000423 method(PyObject *proxy) { \
424 UNWRAP(proxy); \
425 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000426 }
427
428#define WRAP_BINARY(method, generic) \
429 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000430 method(PyObject *x, PyObject *y) { \
431 UNWRAP(x); \
432 UNWRAP(y); \
433 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000434 }
435
Fred Drake31f4d1f2001-10-18 19:21:46 +0000436/* Note that the third arg needs to be checked for NULL since the tp_call
437 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000438 */
Fred Drake8844d522001-10-05 21:52:26 +0000439#define WRAP_TERNARY(method, generic) \
440 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000441 method(PyObject *proxy, PyObject *v, PyObject *w) { \
442 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000443 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000444 if (w != NULL) \
445 UNWRAP(w); \
446 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000447 }
448
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000449#define WRAP_METHOD(method, special) \
450 static PyObject * \
451 method(PyObject *proxy) { \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000452 UNWRAP(proxy); \
453 return PyObject_CallMethod(proxy, special, ""); \
454 }
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000455
Fred Drake8844d522001-10-05 21:52:26 +0000456
457/* direct slots */
458
459WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
460WRAP_UNARY(proxy_str, PyObject_Str)
461WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
462
Fred Drake8844d522001-10-05 21:52:26 +0000463static PyObject *
464proxy_repr(PyWeakReference *proxy)
465{
466 char buf[160];
Barry Warsawd5867562001-11-28 21:01:56 +0000467 PyOS_snprintf(buf, sizeof(buf),
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000468 "<weakproxy at %p to %.100s at %p>", proxy,
469 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
470 PyWeakref_GET_OBJECT(proxy));
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000471 return PyString_FromString(buf);
Fred Drake8844d522001-10-05 21:52:26 +0000472}
473
474
475static int
476proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
477{
478 if (!proxy_checkref(proxy))
479 return -1;
480 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
481}
482
483static int
Fred Drake2a908f62001-12-19 16:44:30 +0000484proxy_compare(PyObject *proxy, PyObject *v)
Fred Drake8844d522001-10-05 21:52:26 +0000485{
Fred Drake2a908f62001-12-19 16:44:30 +0000486 UNWRAP_I(proxy);
487 UNWRAP_I(v);
488 return PyObject_Compare(proxy, v);
Fred Drake8844d522001-10-05 21:52:26 +0000489}
490
491/* number slots */
492WRAP_BINARY(proxy_add, PyNumber_Add)
493WRAP_BINARY(proxy_sub, PyNumber_Subtract)
494WRAP_BINARY(proxy_mul, PyNumber_Multiply)
495WRAP_BINARY(proxy_div, PyNumber_Divide)
Georg Brandl88659b02008-05-20 08:40:43 +0000496WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
497WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000498WRAP_BINARY(proxy_mod, PyNumber_Remainder)
499WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
500WRAP_TERNARY(proxy_pow, PyNumber_Power)
501WRAP_UNARY(proxy_neg, PyNumber_Negative)
502WRAP_UNARY(proxy_pos, PyNumber_Positive)
503WRAP_UNARY(proxy_abs, PyNumber_Absolute)
504WRAP_UNARY(proxy_invert, PyNumber_Invert)
505WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
506WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
507WRAP_BINARY(proxy_and, PyNumber_And)
508WRAP_BINARY(proxy_xor, PyNumber_Xor)
509WRAP_BINARY(proxy_or, PyNumber_Or)
510WRAP_UNARY(proxy_int, PyNumber_Int)
511WRAP_UNARY(proxy_long, PyNumber_Long)
512WRAP_UNARY(proxy_float, PyNumber_Float)
513WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
514WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
515WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
516WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
Georg Brandl88659b02008-05-20 08:40:43 +0000517WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
518WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000519WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
520WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
521WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
522WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
523WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
524WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
525WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandl88659b02008-05-20 08:40:43 +0000526WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000527
Tim Peters403a2032003-11-20 21:21:46 +0000528static int
Fred Drake8844d522001-10-05 21:52:26 +0000529proxy_nonzero(PyWeakReference *proxy)
530{
531 PyObject *o = PyWeakref_GET_OBJECT(proxy);
532 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000533 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000534 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000535}
536
Fred Drake0a4dd392004-07-02 18:57:45 +0000537static void
538proxy_dealloc(PyWeakReference *self)
539{
540 if (self->wr_callback != NULL)
541 PyObject_GC_UnTrack((PyObject *)self);
542 clear_weakref(self);
543 PyObject_GC_Del(self);
544}
545
Fred Drake8844d522001-10-05 21:52:26 +0000546/* sequence slots */
547
548static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000549proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
Fred Drake8844d522001-10-05 21:52:26 +0000550{
551 if (!proxy_checkref(proxy))
552 return NULL;
553 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
554}
555
556static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000557proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
Fred Drake8844d522001-10-05 21:52:26 +0000558{
559 if (!proxy_checkref(proxy))
560 return -1;
561 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
562}
563
564static int
565proxy_contains(PyWeakReference *proxy, PyObject *value)
566{
567 if (!proxy_checkref(proxy))
568 return -1;
569 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
570}
571
572
573/* mapping slots */
574
Martin v. Löwis18e16552006-02-15 17:27:45 +0000575static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000576proxy_length(PyWeakReference *proxy)
577{
578 if (!proxy_checkref(proxy))
579 return -1;
580 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
581}
582
583WRAP_BINARY(proxy_getitem, PyObject_GetItem)
584
585static int
586proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
587{
588 if (!proxy_checkref(proxy))
589 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000590
591 if (value == NULL)
592 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
593 else
594 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000595}
596
Fred Drakef16c3dc2002-08-09 18:34:16 +0000597/* iterator slots */
598
599static PyObject *
600proxy_iter(PyWeakReference *proxy)
601{
602 if (!proxy_checkref(proxy))
603 return NULL;
604 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
605}
606
607static PyObject *
608proxy_iternext(PyWeakReference *proxy)
609{
610 if (!proxy_checkref(proxy))
611 return NULL;
612 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
613}
614
Fred Drake8844d522001-10-05 21:52:26 +0000615
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000616WRAP_METHOD(proxy_unicode, "__unicode__");
617
618
619static PyMethodDef proxy_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000620 {"__unicode__", (PyCFunction)proxy_unicode, METH_NOARGS},
621 {NULL, NULL}
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000622};
623
624
Fred Drake8844d522001-10-05 21:52:26 +0000625static PyNumberMethods proxy_as_number = {
Georg Brandl347b3002006-03-30 11:57:00 +0000626 proxy_add, /*nb_add*/
627 proxy_sub, /*nb_subtract*/
628 proxy_mul, /*nb_multiply*/
629 proxy_div, /*nb_divide*/
630 proxy_mod, /*nb_remainder*/
631 proxy_divmod, /*nb_divmod*/
632 proxy_pow, /*nb_power*/
633 proxy_neg, /*nb_negative*/
634 proxy_pos, /*nb_positive*/
635 proxy_abs, /*nb_absolute*/
636 (inquiry)proxy_nonzero, /*nb_nonzero*/
637 proxy_invert, /*nb_invert*/
638 proxy_lshift, /*nb_lshift*/
639 proxy_rshift, /*nb_rshift*/
640 proxy_and, /*nb_and*/
641 proxy_xor, /*nb_xor*/
642 proxy_or, /*nb_or*/
643 0, /*nb_coerce*/
644 proxy_int, /*nb_int*/
645 proxy_long, /*nb_long*/
646 proxy_float, /*nb_float*/
647 0, /*nb_oct*/
648 0, /*nb_hex*/
649 proxy_iadd, /*nb_inplace_add*/
650 proxy_isub, /*nb_inplace_subtract*/
651 proxy_imul, /*nb_inplace_multiply*/
652 proxy_idiv, /*nb_inplace_divide*/
653 proxy_imod, /*nb_inplace_remainder*/
654 proxy_ipow, /*nb_inplace_power*/
655 proxy_ilshift, /*nb_inplace_lshift*/
656 proxy_irshift, /*nb_inplace_rshift*/
657 proxy_iand, /*nb_inplace_and*/
658 proxy_ixor, /*nb_inplace_xor*/
659 proxy_ior, /*nb_inplace_or*/
Georg Brandl88659b02008-05-20 08:40:43 +0000660 proxy_floor_div, /*nb_floor_divide*/
661 proxy_true_div, /*nb_true_divide*/
662 proxy_ifloor_div, /*nb_inplace_floor_divide*/
663 proxy_itrue_div, /*nb_inplace_true_divide*/
664 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000665};
666
667static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000668 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000669 0, /*sq_concat*/
670 0, /*sq_repeat*/
671 0, /*sq_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000672 (ssizessizeargfunc)proxy_slice, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000673 0, /*sq_ass_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000674 (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000675 (objobjproc)proxy_contains, /* sq_contains */
676};
677
678static PyMappingMethods proxy_as_mapping = {
Georg Brandl347b3002006-03-30 11:57:00 +0000679 (lenfunc)proxy_length, /*mp_length*/
680 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000681 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
682};
683
684
685PyTypeObject
686_PyWeakref_ProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000687 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000688 "weakproxy",
689 sizeof(PyWeakReference),
690 0,
691 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000692 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000693 0, /* tp_print */
694 0, /* tp_getattr */
695 0, /* tp_setattr */
696 proxy_compare, /* tp_compare */
697 (reprfunc)proxy_repr, /* tp_repr */
698 &proxy_as_number, /* tp_as_number */
699 &proxy_as_sequence, /* tp_as_sequence */
700 &proxy_as_mapping, /* tp_as_mapping */
701 0, /* tp_hash */
702 0, /* tp_call */
Georg Brandl347b3002006-03-30 11:57:00 +0000703 proxy_str, /* tp_str */
704 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000705 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000706 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000707 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000708 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
709 0, /* tp_doc */
710 (traverseproc)gc_traverse, /* tp_traverse */
711 (inquiry)gc_clear, /* tp_clear */
712 0, /* tp_richcompare */
713 0, /* tp_weaklistoffset */
714 (getiterfunc)proxy_iter, /* tp_iter */
715 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000716 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000717};
718
719
720PyTypeObject
721_PyWeakref_CallableProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000722 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000723 "weakcallableproxy",
724 sizeof(PyWeakReference),
725 0,
726 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000727 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000728 0, /* tp_print */
729 0, /* tp_getattr */
730 0, /* tp_setattr */
731 proxy_compare, /* tp_compare */
732 (unaryfunc)proxy_repr, /* tp_repr */
733 &proxy_as_number, /* tp_as_number */
734 &proxy_as_sequence, /* tp_as_sequence */
735 &proxy_as_mapping, /* tp_as_mapping */
736 0, /* tp_hash */
737 proxy_call, /* tp_call */
738 proxy_str, /* tp_str */
Georg Brandl347b3002006-03-30 11:57:00 +0000739 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000740 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000741 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000742 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000743 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
744 0, /* tp_doc */
745 (traverseproc)gc_traverse, /* tp_traverse */
746 (inquiry)gc_clear, /* tp_clear */
747 0, /* tp_richcompare */
748 0, /* tp_weaklistoffset */
749 (getiterfunc)proxy_iter, /* tp_iter */
750 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000751};
752
753
Fred Drake8844d522001-10-05 21:52:26 +0000754
755PyObject *
756PyWeakref_NewRef(PyObject *ob, PyObject *callback)
757{
758 PyWeakReference *result = NULL;
759 PyWeakReference **list;
760 PyWeakReference *ref, *proxy;
761
Christian Heimese93237d2007-12-19 02:37:44 +0000762 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000763 PyErr_Format(PyExc_TypeError,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000764 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000765 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000766 return NULL;
767 }
768 list = GET_WEAKREFS_LISTPTR(ob);
769 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000770 if (callback == Py_None)
771 callback = NULL;
772 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000773 /* return existing weak reference if it exists */
774 result = ref;
775 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000776 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000777 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000778 /* Note: new_weakref() can trigger cyclic GC, so the weakref
779 list on ob can be mutated. This means that the ref and
780 proxy pointers we got back earlier may have been collected,
781 so we need to compute these values again before we use
782 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000783 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000784 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000785 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000786 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000787 if (ref == NULL)
788 insert_head(result, list);
789 else {
790 /* Someone else added a ref without a callback
791 during GC. Return that one instead of this one
792 to avoid violating the invariants of the list
793 of weakrefs for ob. */
794 Py_DECREF(result);
795 Py_INCREF(ref);
796 result = ref;
797 }
Fred Drake8844d522001-10-05 21:52:26 +0000798 }
799 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000800 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000801
Fred Drakebc875f52004-02-04 23:14:14 +0000802 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000803 if (prev == NULL)
804 insert_head(result, list);
805 else
806 insert_after(result, prev);
807 }
Fred Drake8844d522001-10-05 21:52:26 +0000808 }
809 }
810 return (PyObject *) result;
811}
812
813
814PyObject *
815PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
816{
817 PyWeakReference *result = NULL;
818 PyWeakReference **list;
819 PyWeakReference *ref, *proxy;
820
Christian Heimese93237d2007-12-19 02:37:44 +0000821 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000822 PyErr_Format(PyExc_TypeError,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000823 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000824 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000825 return NULL;
826 }
827 list = GET_WEAKREFS_LISTPTR(ob);
828 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000829 if (callback == Py_None)
830 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000831 if (callback == NULL)
832 /* attempt to return an existing weak reference if it exists */
833 result = proxy;
834 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000835 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000836 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000837 /* Note: new_weakref() can trigger cyclic GC, so the weakref
838 list on ob can be mutated. This means that the ref and
839 proxy pointers we got back earlier may have been collected,
840 so we need to compute these values again before we use
841 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000842 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000843 if (result != NULL) {
844 PyWeakReference *prev;
845
846 if (PyCallable_Check(ob))
Christian Heimese93237d2007-12-19 02:37:44 +0000847 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000848 else
Christian Heimese93237d2007-12-19 02:37:44 +0000849 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000850 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000851 if (callback == NULL) {
852 if (proxy != NULL) {
853 /* Someone else added a proxy without a callback
854 during GC. Return that one instead of this one
855 to avoid violating the invariants of the list
856 of weakrefs for ob. */
857 Py_DECREF(result);
858 Py_INCREF(result = proxy);
859 goto skip_insert;
860 }
Fred Drake8844d522001-10-05 21:52:26 +0000861 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000862 }
Fred Drake8844d522001-10-05 21:52:26 +0000863 else
864 prev = (proxy == NULL) ? ref : proxy;
865
866 if (prev == NULL)
867 insert_head(result, list);
868 else
869 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000870 skip_insert:
871 ;
Fred Drake8844d522001-10-05 21:52:26 +0000872 }
873 }
874 return (PyObject *) result;
875}
876
877
878PyObject *
879PyWeakref_GetObject(PyObject *ref)
880{
881 if (ref == NULL || !PyWeakref_Check(ref)) {
882 PyErr_BadInternalCall();
883 return NULL;
884 }
885 return PyWeakref_GET_OBJECT(ref);
886}
887
Tim Petersead8b7a2004-10-30 23:09:22 +0000888/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
889 * handle_weakrefs().
890 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000891static void
892handle_callback(PyWeakReference *ref, PyObject *callback)
893{
Georg Brandl684fd0c2006-05-25 19:15:31 +0000894 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000895
896 if (cbresult == NULL)
897 PyErr_WriteUnraisable(callback);
898 else
899 Py_DECREF(cbresult);
900}
901
902/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000903 *
904 * This iterates through the weak references for 'object' and calls callbacks
905 * for those references which have one. It returns when all callbacks have
906 * been attempted.
907 */
908void
909PyObject_ClearWeakRefs(PyObject *object)
910{
911 PyWeakReference **list;
912
913 if (object == NULL
Christian Heimese93237d2007-12-19 02:37:44 +0000914 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000915 || object->ob_refcnt != 0) {
916 PyErr_BadInternalCall();
917 return;
918 }
919 list = GET_WEAKREFS_LISTPTR(object);
920 /* Remove the callback-less basic and proxy references */
921 if (*list != NULL && (*list)->wr_callback == NULL) {
922 clear_weakref(*list);
923 if (*list != NULL && (*list)->wr_callback == NULL)
924 clear_weakref(*list);
925 }
926 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000927 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000928 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000929 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000930
Serhiy Storchaka07e03ab2015-03-30 09:53:06 +0300931 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000932 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000933 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000934
Fred Drakeef8ebd12001-12-10 23:44:54 +0000935 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000936 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000937 if (callback != NULL) {
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000938 if (current->ob_refcnt > 0)
939 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000940 Py_DECREF(callback);
941 }
Fred Drake8844d522001-10-05 21:52:26 +0000942 }
943 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000944 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000945 Py_ssize_t i = 0;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000946
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000947 tuple = PyTuple_New(count * 2);
948 if (tuple == NULL) {
Serhiy Storchaka07e03ab2015-03-30 09:53:06 +0300949 _PyErr_ReplaceException(err_type, err_value, err_tb);
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000950 return;
951 }
Fred Drake8844d522001-10-05 21:52:26 +0000952
953 for (i = 0; i < count; ++i) {
954 PyWeakReference *next = current->wr_next;
955
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000956 if (current->ob_refcnt > 0)
957 {
958 Py_INCREF(current);
959 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
960 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
961 }
962 else {
963 Py_DECREF(current->wr_callback);
964 }
Fred Drake8844d522001-10-05 21:52:26 +0000965 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000966 clear_weakref(current);
967 current = next;
968 }
969 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000970 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000971
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000972 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000973 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000974 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
975 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000976 }
Fred Drake8844d522001-10-05 21:52:26 +0000977 }
978 Py_DECREF(tuple);
979 }
Serhiy Storchaka07e03ab2015-03-30 09:53:06 +0300980 assert(!PyErr_Occurred());
981 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000982 }
983}