blob: 417f07579ab50e759d52ea5222056e4f5da74349 [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
Thomas Wouters0e3f5912006-08-11 14:57:12 +00009Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +000010_PyWeakref_GetWeakrefCount(PyWeakReference *head)
11{
Thomas Wouters0e3f5912006-08-11 14:57:12 +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 Pitrou62a0d6e2012-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 Pitrouf95a1b32010-05-09 15:52:27 +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 Heimes90aa7642007-12-19 02:45:37 +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 Wouters49fd7fa2006-04-21 10:40:58 +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
Benjamin Peterson8f67d082010-10-17 20:54:53 +0000141static Py_hash_t
Fred Drake8844d522001-10-05 21:52:26 +0000142weakref_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 Pitrouf95a1b32010-05-09 15:52:27 +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 (PyUnicode_Check(nameobj))
169 name = _PyUnicode_AsString(nameobj);
Gregory P. Smithce9e3c32013-02-01 16:14:00 -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 Pitrouf95a1b32010-05-09 15:52:27 +0000185 Py_XDECREF(nameobj);
Fred Drake8844d522001-10-05 21:52:26 +0000186 }
Walter Dörwald1ab83302007-05-18 17:15:44 +0000187 return PyUnicode_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{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000197 if ((op != Py_EQ && op != Py_NE) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 !PyWeakref_Check(self) ||
199 !PyWeakref_Check(other)) {
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 Pitroue11fecb2012-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{
276 /* XXX Should check that kwargs == NULL or is empty. */
277 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
278}
279
280static PyObject *
281weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
282{
283 PyWeakReference *self = NULL;
284 PyObject *ob, *callback = NULL;
285
286 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
287 PyWeakReference *ref, *proxy;
288 PyWeakReference **list;
289
Christian Heimes90aa7642007-12-19 02:45:37 +0000290 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000291 PyErr_Format(PyExc_TypeError,
292 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000293 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000294 return NULL;
295 }
296 if (callback == Py_None)
297 callback = NULL;
298 list = GET_WEAKREFS_LISTPTR(ob);
299 get_basic_refs(*list, &ref, &proxy);
300 if (callback == NULL && type == &_PyWeakref_RefType) {
301 if (ref != NULL) {
302 /* We can re-use an existing reference. */
303 Py_INCREF(ref);
304 return (PyObject *)ref;
305 }
306 }
307 /* We have to create a new reference. */
308 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
309 list on ob can be mutated. This means that the ref and
310 proxy pointers we got back earlier may have been collected,
311 so we need to compute these values again before we use
312 them. */
313 self = (PyWeakReference *) (type->tp_alloc(type, 0));
314 if (self != NULL) {
315 init_weakref(self, ob, callback);
316 if (callback == NULL && type == &_PyWeakref_RefType) {
317 insert_head(self, list);
318 }
319 else {
320 PyWeakReference *prev;
321
322 get_basic_refs(*list, &ref, &proxy);
323 prev = (proxy == NULL) ? ref : proxy;
324 if (prev == NULL)
325 insert_head(self, list);
326 else
327 insert_after(self, prev);
328 }
329 }
330 }
331 return (PyObject *)self;
332}
333
334static int
335weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
336{
337 PyObject *tmp;
338
339 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
340 return 0;
341 else
Benjamin Peterson9aa42992008-09-10 21:57:34 +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öwis9f2e3462007-07-21 17:22:18 +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 Pitrouf95a1b32010-05-09 15:52:27 +0000353 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000354 0, /*tp_getattr*/
355 0, /*tp_setattr*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356 0, /*tp_reserved*/
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*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000367 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000368 | 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 Pitrouf95a1b32010-05-09 15:52:27 +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*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +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 Peterson32019772009-11-19 03:08:32 +0000449#define WRAP_METHOD(method, special) \
450 static PyObject * \
451 method(PyObject *proxy) { \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000452 UNWRAP(proxy); \
453 return PyObject_CallMethod(proxy, special, ""); \
454 }
Benjamin Peterson32019772009-11-19 03:08:32 +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 Pitrouf95a1b32010-05-09 15:52:27 +0000468 "<weakproxy at %p to %.100s at %p>", proxy,
469 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
470 PyWeakref_GET_OBJECT(proxy));
Walter Dörwald1ab83302007-05-18 17:15:44 +0000471 return PyUnicode_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
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000483static PyObject *
484proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000485{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000486 UNWRAP(proxy);
487 UNWRAP(v);
488 return PyObject_RichCompare(proxy, v, op);
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)
Georg Brandlb533e262008-05-25 18:19:30 +0000495WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
496WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000497WRAP_BINARY(proxy_mod, PyNumber_Remainder)
498WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
499WRAP_TERNARY(proxy_pow, PyNumber_Power)
500WRAP_UNARY(proxy_neg, PyNumber_Negative)
501WRAP_UNARY(proxy_pos, PyNumber_Positive)
502WRAP_UNARY(proxy_abs, PyNumber_Absolute)
503WRAP_UNARY(proxy_invert, PyNumber_Invert)
504WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
505WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
506WRAP_BINARY(proxy_and, PyNumber_And)
507WRAP_BINARY(proxy_xor, PyNumber_Xor)
508WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000509WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000510WRAP_UNARY(proxy_float, PyNumber_Float)
511WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
512WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
513WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000514WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
515WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000516WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
517WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
518WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
519WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
520WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
521WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
522WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000523WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000524
Tim Peters403a2032003-11-20 21:21:46 +0000525static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000526proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000527{
528 PyObject *o = PyWeakref_GET_OBJECT(proxy);
529 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000530 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000531 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000532}
533
Fred Drake0a4dd392004-07-02 18:57:45 +0000534static void
535proxy_dealloc(PyWeakReference *self)
536{
537 if (self->wr_callback != NULL)
538 PyObject_GC_UnTrack((PyObject *)self);
539 clear_weakref(self);
540 PyObject_GC_Del(self);
541}
542
Fred Drake8844d522001-10-05 21:52:26 +0000543/* sequence slots */
544
Fred Drake8844d522001-10-05 21:52:26 +0000545static int
546proxy_contains(PyWeakReference *proxy, PyObject *value)
547{
548 if (!proxy_checkref(proxy))
549 return -1;
550 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
551}
552
553
554/* mapping slots */
555
Martin v. Löwis18e16552006-02-15 17:27:45 +0000556static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000557proxy_length(PyWeakReference *proxy)
558{
559 if (!proxy_checkref(proxy))
560 return -1;
561 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
562}
563
564WRAP_BINARY(proxy_getitem, PyObject_GetItem)
565
566static int
567proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
568{
569 if (!proxy_checkref(proxy))
570 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000571
572 if (value == NULL)
573 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
574 else
575 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000576}
577
Fred Drakef16c3dc2002-08-09 18:34:16 +0000578/* iterator slots */
579
580static PyObject *
581proxy_iter(PyWeakReference *proxy)
582{
583 if (!proxy_checkref(proxy))
584 return NULL;
585 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
586}
587
588static PyObject *
589proxy_iternext(PyWeakReference *proxy)
590{
591 if (!proxy_checkref(proxy))
592 return NULL;
593 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
594}
595
Fred Drake8844d522001-10-05 21:52:26 +0000596
Victor Stinner3e2b7172010-11-09 09:32:19 +0000597WRAP_METHOD(proxy_bytes, "__bytes__")
Benjamin Peterson32019772009-11-19 03:08:32 +0000598
599
600static PyMethodDef proxy_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 {"__bytes__", (PyCFunction)proxy_bytes, METH_NOARGS},
602 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000603};
604
605
Fred Drake8844d522001-10-05 21:52:26 +0000606static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000607 proxy_add, /*nb_add*/
608 proxy_sub, /*nb_subtract*/
609 proxy_mul, /*nb_multiply*/
610 proxy_mod, /*nb_remainder*/
611 proxy_divmod, /*nb_divmod*/
612 proxy_pow, /*nb_power*/
613 proxy_neg, /*nb_negative*/
614 proxy_pos, /*nb_positive*/
615 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000616 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000617 proxy_invert, /*nb_invert*/
618 proxy_lshift, /*nb_lshift*/
619 proxy_rshift, /*nb_rshift*/
620 proxy_and, /*nb_and*/
621 proxy_xor, /*nb_xor*/
622 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000623 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000624 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000625 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000626 proxy_iadd, /*nb_inplace_add*/
627 proxy_isub, /*nb_inplace_subtract*/
628 proxy_imul, /*nb_inplace_multiply*/
629 proxy_imod, /*nb_inplace_remainder*/
630 proxy_ipow, /*nb_inplace_power*/
631 proxy_ilshift, /*nb_inplace_lshift*/
632 proxy_irshift, /*nb_inplace_rshift*/
633 proxy_iand, /*nb_inplace_and*/
634 proxy_ixor, /*nb_inplace_xor*/
635 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000636 proxy_floor_div, /*nb_floor_divide*/
637 proxy_true_div, /*nb_true_divide*/
638 proxy_ifloor_div, /*nb_inplace_floor_divide*/
639 proxy_itrue_div, /*nb_inplace_true_divide*/
640 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000641};
642
643static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000644 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000645 0, /*sq_concat*/
646 0, /*sq_repeat*/
647 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000648 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000649 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000651 (objobjproc)proxy_contains, /* sq_contains */
652};
653
654static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000655 (lenfunc)proxy_length, /*mp_length*/
656 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000657 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
658};
659
660
661PyTypeObject
662_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000663 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000664 "weakproxy",
665 sizeof(PyWeakReference),
666 0,
667 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000668 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 0, /* tp_print */
670 0, /* tp_getattr */
671 0, /* tp_setattr */
672 0, /* tp_reserved */
673 (reprfunc)proxy_repr, /* tp_repr */
674 &proxy_as_number, /* tp_as_number */
675 &proxy_as_sequence, /* tp_as_sequence */
676 &proxy_as_mapping, /* tp_as_mapping */
677 0, /* tp_hash */
678 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000679 proxy_str, /* tp_str */
680 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000681 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000683 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000684 0, /* tp_doc */
685 (traverseproc)gc_traverse, /* tp_traverse */
686 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000687 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000688 0, /* tp_weaklistoffset */
689 (getiterfunc)proxy_iter, /* tp_iter */
690 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000692};
693
694
695PyTypeObject
696_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000697 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000698 "weakcallableproxy",
699 sizeof(PyWeakReference),
700 0,
701 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000702 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000703 0, /* tp_print */
704 0, /* tp_getattr */
705 0, /* tp_setattr */
706 0, /* tp_reserved */
707 (unaryfunc)proxy_repr, /* tp_repr */
708 &proxy_as_number, /* tp_as_number */
709 &proxy_as_sequence, /* tp_as_sequence */
710 &proxy_as_mapping, /* tp_as_mapping */
711 0, /* tp_hash */
712 proxy_call, /* tp_call */
713 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000714 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000715 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000716 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000717 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000718 0, /* tp_doc */
719 (traverseproc)gc_traverse, /* tp_traverse */
720 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000721 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000722 0, /* tp_weaklistoffset */
723 (getiterfunc)proxy_iter, /* tp_iter */
724 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000725};
726
727
Fred Drake8844d522001-10-05 21:52:26 +0000728
729PyObject *
730PyWeakref_NewRef(PyObject *ob, PyObject *callback)
731{
732 PyWeakReference *result = NULL;
733 PyWeakReference **list;
734 PyWeakReference *ref, *proxy;
735
Christian Heimes90aa7642007-12-19 02:45:37 +0000736 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000737 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000739 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000740 return NULL;
741 }
742 list = GET_WEAKREFS_LISTPTR(ob);
743 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000744 if (callback == Py_None)
745 callback = NULL;
746 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000747 /* return existing weak reference if it exists */
748 result = ref;
749 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000750 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000751 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000752 /* Note: new_weakref() can trigger cyclic GC, so the weakref
753 list on ob can be mutated. This means that the ref and
754 proxy pointers we got back earlier may have been collected,
755 so we need to compute these values again before we use
756 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000757 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000758 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000759 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000760 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000761 if (ref == NULL)
762 insert_head(result, list);
763 else {
764 /* Someone else added a ref without a callback
765 during GC. Return that one instead of this one
766 to avoid violating the invariants of the list
767 of weakrefs for ob. */
768 Py_DECREF(result);
769 Py_INCREF(ref);
770 result = ref;
771 }
Fred Drake8844d522001-10-05 21:52:26 +0000772 }
773 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000774 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000775
Fred Drakebc875f52004-02-04 23:14:14 +0000776 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000777 if (prev == NULL)
778 insert_head(result, list);
779 else
780 insert_after(result, prev);
781 }
Fred Drake8844d522001-10-05 21:52:26 +0000782 }
783 }
784 return (PyObject *) result;
785}
786
787
788PyObject *
789PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
790{
791 PyWeakReference *result = NULL;
792 PyWeakReference **list;
793 PyWeakReference *ref, *proxy;
794
Christian Heimes90aa7642007-12-19 02:45:37 +0000795 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000796 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000798 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000799 return NULL;
800 }
801 list = GET_WEAKREFS_LISTPTR(ob);
802 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000803 if (callback == Py_None)
804 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000805 if (callback == NULL)
806 /* attempt to return an existing weak reference if it exists */
807 result = proxy;
808 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000809 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000810 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000811 /* Note: new_weakref() can trigger cyclic GC, so the weakref
812 list on ob can be mutated. This means that the ref and
813 proxy pointers we got back earlier may have been collected,
814 so we need to compute these values again before we use
815 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000816 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000817 if (result != NULL) {
818 PyWeakReference *prev;
819
820 if (PyCallable_Check(ob))
Christian Heimes90aa7642007-12-19 02:45:37 +0000821 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000822 else
Christian Heimes90aa7642007-12-19 02:45:37 +0000823 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000824 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000825 if (callback == NULL) {
826 if (proxy != NULL) {
827 /* Someone else added a proxy without a callback
828 during GC. Return that one instead of this one
829 to avoid violating the invariants of the list
830 of weakrefs for ob. */
831 Py_DECREF(result);
832 Py_INCREF(result = proxy);
833 goto skip_insert;
834 }
Fred Drake8844d522001-10-05 21:52:26 +0000835 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000836 }
Fred Drake8844d522001-10-05 21:52:26 +0000837 else
838 prev = (proxy == NULL) ? ref : proxy;
839
840 if (prev == NULL)
841 insert_head(result, list);
842 else
843 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000844 skip_insert:
845 ;
Fred Drake8844d522001-10-05 21:52:26 +0000846 }
847 }
848 return (PyObject *) result;
849}
850
851
852PyObject *
853PyWeakref_GetObject(PyObject *ref)
854{
855 if (ref == NULL || !PyWeakref_Check(ref)) {
856 PyErr_BadInternalCall();
857 return NULL;
858 }
859 return PyWeakref_GET_OBJECT(ref);
860}
861
Tim Petersead8b7a2004-10-30 23:09:22 +0000862/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
863 * handle_weakrefs().
864 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000865static void
866handle_callback(PyWeakReference *ref, PyObject *callback)
867{
Thomas Wouters477c8d52006-05-27 19:21:47 +0000868 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000869
870 if (cbresult == NULL)
871 PyErr_WriteUnraisable(callback);
872 else
873 Py_DECREF(cbresult);
874}
875
876/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000877 *
878 * This iterates through the weak references for 'object' and calls callbacks
879 * for those references which have one. It returns when all callbacks have
880 * been attempted.
881 */
882void
883PyObject_ClearWeakRefs(PyObject *object)
884{
885 PyWeakReference **list;
886
887 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000888 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000889 || object->ob_refcnt != 0) {
890 PyErr_BadInternalCall();
891 return;
892 }
893 list = GET_WEAKREFS_LISTPTR(object);
894 /* Remove the callback-less basic and proxy references */
895 if (*list != NULL && (*list)->wr_callback == NULL) {
896 clear_weakref(*list);
897 if (*list != NULL && (*list)->wr_callback == NULL)
898 clear_weakref(*list);
899 }
900 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000901 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000902 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000903 int restore_error = PyErr_Occurred() ? 1 : 0;
904 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000905
Fred Drakeef8ebd12001-12-10 23:44:54 +0000906 if (restore_error)
907 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000908 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000909 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000910
Fred Drakeef8ebd12001-12-10 23:44:54 +0000911 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000912 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000913 if (callback != NULL) {
Benjamin Petersona38d1562008-06-16 20:47:12 +0000914 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000915 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000916 Py_DECREF(callback);
917 }
Fred Drake8844d522001-10-05 21:52:26 +0000918 }
919 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000920 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000921 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000922
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000923 tuple = PyTuple_New(count * 2);
924 if (tuple == NULL) {
925 if (restore_error)
926 PyErr_Fetch(&err_type, &err_value, &err_tb);
927 return;
928 }
Fred Drake8844d522001-10-05 21:52:26 +0000929
930 for (i = 0; i < count; ++i) {
931 PyWeakReference *next = current->wr_next;
932
Benjamin Petersona38d1562008-06-16 20:47:12 +0000933 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000934 {
935 Py_INCREF(current);
936 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
937 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
938 }
939 else {
940 Py_DECREF(current->wr_callback);
941 }
Fred Drake8844d522001-10-05 21:52:26 +0000942 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000943 clear_weakref(current);
944 current = next;
945 }
946 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000947 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000948
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000949 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000950 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000951 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
952 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000953 }
Fred Drake8844d522001-10-05 21:52:26 +0000954 }
955 Py_DECREF(tuple);
956 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000957 if (restore_error)
958 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000959 }
960}