blob: dfaa1b9f8ec27f53e727037cc8aa37e98fa29295 [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
55 if (PyWeakref_GET_OBJECT(self) != Py_None) {
56 PyWeakReference **list = GET_WEAKREFS_LISTPTR(
57 PyWeakref_GET_OBJECT(self));
58
59 if (*list == self)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
61 then the weakref list itself (and thus the value of *list) will
62 end up being set to NULL. */
Fred Drake8844d522001-10-05 21:52:26 +000063 *list = self->wr_next;
64 self->wr_object = Py_None;
Fred Drake8844d522001-10-05 21:52:26 +000065 if (self->wr_prev != NULL)
66 self->wr_prev->wr_next = self->wr_next;
67 if (self->wr_next != NULL)
68 self->wr_next->wr_prev = self->wr_prev;
69 self->wr_prev = NULL;
70 self->wr_next = NULL;
Tim Peters403a2032003-11-20 21:21:46 +000071 }
72 if (callback != NULL) {
73 Py_DECREF(callback);
74 self->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +000075 }
76}
77
Tim Peters403a2032003-11-20 21:21:46 +000078/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
79 * the callback intact and uncalled. It must be possible to call self's
80 * tp_dealloc() after calling this, so self has to be left in a sane enough
81 * state for that to work. We expect tp_dealloc to decref the callback
82 * then. The reason for not letting clear_weakref() decref the callback
83 * right now is that if the callback goes away, that may in turn trigger
84 * another callback (if a weak reference to the callback exists) -- running
85 * arbitrary Python code in the middle of gc is a disaster. The convolution
86 * here allows gc to delay triggering such callbacks until the world is in
87 * a sane state again.
88 */
89void
90_PyWeakref_ClearRef(PyWeakReference *self)
91{
92 PyObject *callback;
93
94 assert(self != NULL);
95 assert(PyWeakref_Check(self));
96 /* Preserve and restore the callback around clear_weakref. */
97 callback = self->wr_callback;
98 self->wr_callback = NULL;
99 clear_weakref(self);
100 self->wr_callback = callback;
101}
Fred Drake8844d522001-10-05 21:52:26 +0000102
103static void
Fred Drake0a4dd392004-07-02 18:57:45 +0000104weakref_dealloc(PyObject *self)
Fred Drake8844d522001-10-05 21:52:26 +0000105{
Fred Drake0a4dd392004-07-02 18:57:45 +0000106 PyObject_GC_UnTrack(self);
107 clear_weakref((PyWeakReference *) self);
Christian Heimes90aa7642007-12-19 02:45:37 +0000108 Py_TYPE(self)->tp_free(self);
Fred Drake8844d522001-10-05 21:52:26 +0000109}
110
111
112static int
113gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
114{
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000115 Py_VISIT(self->wr_callback);
Fred Drake8844d522001-10-05 21:52:26 +0000116 return 0;
117}
118
119
120static int
121gc_clear(PyWeakReference *self)
122{
123 clear_weakref(self);
124 return 0;
125}
126
127
128static PyObject *
129weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
130{
Martin v. Löwis15e62742006-02-27 16:46:16 +0000131 static char *kwlist[] = {NULL};
Fred Drake8844d522001-10-05 21:52:26 +0000132
Martin v. Löwis15e62742006-02-27 16:46:16 +0000133 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
Fred Drake8844d522001-10-05 21:52:26 +0000134 PyObject *object = PyWeakref_GET_OBJECT(self);
135 Py_INCREF(object);
136 return (object);
137 }
138 return NULL;
139}
140
141
Benjamin Peterson8f67d082010-10-17 20:54:53 +0000142static Py_hash_t
Fred Drake8844d522001-10-05 21:52:26 +0000143weakref_hash(PyWeakReference *self)
144{
145 if (self->hash != -1)
146 return self->hash;
147 if (PyWeakref_GET_OBJECT(self) == Py_None) {
148 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
149 return -1;
150 }
151 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
152 return self->hash;
153}
Tim Peters403a2032003-11-20 21:21:46 +0000154
Fred Drake8844d522001-10-05 21:52:26 +0000155
156static PyObject *
157weakref_repr(PyWeakReference *self)
158{
159 char buffer[256];
160 if (PyWeakref_GET_OBJECT(self) == Py_None) {
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000161 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
Fred Drake8844d522001-10-05 21:52:26 +0000162 }
163 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000164 char *name = NULL;
165 PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
166 "__name__");
167 if (nameobj == NULL)
168 PyErr_Clear();
169 else if (PyUnicode_Check(nameobj))
170 name = _PyUnicode_AsString(nameobj);
Brett Cannonb94767f2011-02-22 20:15:44 +0000171 if (name)
172 PyOS_snprintf(buffer, sizeof(buffer),
173 "<weakref at %p; to '%.50s' at %p (%s)>",
174 self,
175 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
176 PyWeakref_GET_OBJECT(self),
177 name);
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) {
205 PyObject *res = self==other ? Py_True : Py_False;
206 Py_INCREF(res);
207 return res;
208 }
209 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
210 PyWeakref_GET_OBJECT(other), op);
211}
212
Fred Drake0a4dd392004-07-02 18:57:45 +0000213/* Given the head of an object's list of weak references, extract the
214 * two callback-less refs (ref and proxy). Used to determine if the
215 * shared references exist and to determine the back link for newly
216 * inserted references.
217 */
218static void
219get_basic_refs(PyWeakReference *head,
220 PyWeakReference **refp, PyWeakReference **proxyp)
221{
222 *refp = NULL;
223 *proxyp = NULL;
224
225 if (head != NULL && head->wr_callback == NULL) {
226 /* We need to be careful that the "basic refs" aren't
227 subclasses of the main types. That complicates this a
228 little. */
229 if (PyWeakref_CheckRefExact(head)) {
230 *refp = head;
231 head = head->wr_next;
232 }
233 if (head != NULL
234 && head->wr_callback == NULL
235 && PyWeakref_CheckProxy(head)) {
236 *proxyp = head;
237 /* head = head->wr_next; */
238 }
239 }
240}
241
242/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
243static void
244insert_after(PyWeakReference *newref, PyWeakReference *prev)
245{
246 newref->wr_prev = prev;
247 newref->wr_next = prev->wr_next;
248 if (prev->wr_next != NULL)
249 prev->wr_next->wr_prev = newref;
250 prev->wr_next = newref;
251}
252
253/* Insert 'newref' at the head of the list; 'list' points to the variable
254 * that stores the head.
255 */
256static void
257insert_head(PyWeakReference *newref, PyWeakReference **list)
258{
259 PyWeakReference *next = *list;
260
261 newref->wr_prev = NULL;
262 newref->wr_next = next;
263 if (next != NULL)
264 next->wr_prev = newref;
265 *list = newref;
266}
267
268static int
269parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
270 PyObject **obp, PyObject **callbackp)
271{
272 /* XXX Should check that kwargs == NULL or is empty. */
273 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
274}
275
276static PyObject *
277weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
278{
279 PyWeakReference *self = NULL;
280 PyObject *ob, *callback = NULL;
281
282 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
283 PyWeakReference *ref, *proxy;
284 PyWeakReference **list;
285
Christian Heimes90aa7642007-12-19 02:45:37 +0000286 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000287 PyErr_Format(PyExc_TypeError,
288 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000289 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000290 return NULL;
291 }
292 if (callback == Py_None)
293 callback = NULL;
294 list = GET_WEAKREFS_LISTPTR(ob);
295 get_basic_refs(*list, &ref, &proxy);
296 if (callback == NULL && type == &_PyWeakref_RefType) {
297 if (ref != NULL) {
298 /* We can re-use an existing reference. */
299 Py_INCREF(ref);
300 return (PyObject *)ref;
301 }
302 }
303 /* We have to create a new reference. */
304 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
305 list on ob can be mutated. This means that the ref and
306 proxy pointers we got back earlier may have been collected,
307 so we need to compute these values again before we use
308 them. */
309 self = (PyWeakReference *) (type->tp_alloc(type, 0));
310 if (self != NULL) {
311 init_weakref(self, ob, callback);
312 if (callback == NULL && type == &_PyWeakref_RefType) {
313 insert_head(self, list);
314 }
315 else {
316 PyWeakReference *prev;
317
318 get_basic_refs(*list, &ref, &proxy);
319 prev = (proxy == NULL) ? ref : proxy;
320 if (prev == NULL)
321 insert_head(self, list);
322 else
323 insert_after(self, prev);
324 }
325 }
326 }
327 return (PyObject *)self;
328}
329
330static int
331weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
332{
333 PyObject *tmp;
334
335 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
336 return 0;
337 else
Benjamin Peterson9aa42992008-09-10 21:57:34 +0000338 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000339}
340
Fred Drake8844d522001-10-05 21:52:26 +0000341
342PyTypeObject
343_PyWeakref_RefType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000344 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000345 "weakref",
346 sizeof(PyWeakReference),
347 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000348 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000349 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000350 0, /*tp_getattr*/
351 0, /*tp_setattr*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000352 0, /*tp_reserved*/
Fred Drake8844d522001-10-05 21:52:26 +0000353 (reprfunc)weakref_repr, /*tp_repr*/
354 0, /*tp_as_number*/
355 0, /*tp_as_sequence*/
356 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000357 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000358 (ternaryfunc)weakref_call, /*tp_call*/
359 0, /*tp_str*/
360 0, /*tp_getattro*/
361 0, /*tp_setattro*/
362 0, /*tp_as_buffer*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000363 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000364 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000365 0, /*tp_doc*/
366 (traverseproc)gc_traverse, /*tp_traverse*/
367 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000368 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000369 0, /*tp_weaklistoffset*/
370 0, /*tp_iter*/
371 0, /*tp_iternext*/
372 0, /*tp_methods*/
373 0, /*tp_members*/
374 0, /*tp_getset*/
375 0, /*tp_base*/
376 0, /*tp_dict*/
377 0, /*tp_descr_get*/
378 0, /*tp_descr_set*/
379 0, /*tp_dictoffset*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000380 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000381 PyType_GenericAlloc, /*tp_alloc*/
382 weakref___new__, /*tp_new*/
383 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000384};
385
386
387static int
388proxy_checkref(PyWeakReference *proxy)
389{
390 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
391 PyErr_SetString(PyExc_ReferenceError,
392 "weakly-referenced object no longer exists");
393 return 0;
394 }
395 return 1;
396}
397
398
Fred Drake73006d02001-10-18 18:04:18 +0000399/* If a parameter is a proxy, check that it is still "live" and wrap it,
400 * replacing the original value with the raw object. Raises ReferenceError
401 * if the param is a dead proxy.
402 */
403#define UNWRAP(o) \
404 if (PyWeakref_CheckProxy(o)) { \
405 if (!proxy_checkref((PyWeakReference *)o)) \
406 return NULL; \
407 o = PyWeakref_GET_OBJECT(o); \
408 }
409
Fred Drake2a908f62001-12-19 16:44:30 +0000410#define UNWRAP_I(o) \
411 if (PyWeakref_CheckProxy(o)) { \
412 if (!proxy_checkref((PyWeakReference *)o)) \
413 return -1; \
414 o = PyWeakref_GET_OBJECT(o); \
415 }
416
Fred Drake8844d522001-10-05 21:52:26 +0000417#define WRAP_UNARY(method, generic) \
418 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000419 method(PyObject *proxy) { \
420 UNWRAP(proxy); \
421 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000422 }
423
424#define WRAP_BINARY(method, generic) \
425 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000426 method(PyObject *x, PyObject *y) { \
427 UNWRAP(x); \
428 UNWRAP(y); \
429 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000430 }
431
Fred Drake31f4d1f2001-10-18 19:21:46 +0000432/* Note that the third arg needs to be checked for NULL since the tp_call
433 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000434 */
Fred Drake8844d522001-10-05 21:52:26 +0000435#define WRAP_TERNARY(method, generic) \
436 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000437 method(PyObject *proxy, PyObject *v, PyObject *w) { \
438 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000439 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000440 if (w != NULL) \
441 UNWRAP(w); \
442 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000443 }
444
Benjamin Peterson32019772009-11-19 03:08:32 +0000445#define WRAP_METHOD(method, special) \
446 static PyObject * \
447 method(PyObject *proxy) { \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448 UNWRAP(proxy); \
449 return PyObject_CallMethod(proxy, special, ""); \
450 }
Benjamin Peterson32019772009-11-19 03:08:32 +0000451
Fred Drake8844d522001-10-05 21:52:26 +0000452
453/* direct slots */
454
455WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
456WRAP_UNARY(proxy_str, PyObject_Str)
457WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
458
Fred Drake8844d522001-10-05 21:52:26 +0000459static PyObject *
460proxy_repr(PyWeakReference *proxy)
461{
462 char buf[160];
Barry Warsawd5867562001-11-28 21:01:56 +0000463 PyOS_snprintf(buf, sizeof(buf),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 "<weakproxy at %p to %.100s at %p>", proxy,
465 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
466 PyWeakref_GET_OBJECT(proxy));
Walter Dörwald1ab83302007-05-18 17:15:44 +0000467 return PyUnicode_FromString(buf);
Fred Drake8844d522001-10-05 21:52:26 +0000468}
469
470
471static int
472proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
473{
474 if (!proxy_checkref(proxy))
475 return -1;
476 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
477}
478
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000479static PyObject *
480proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000481{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000482 UNWRAP(proxy);
483 UNWRAP(v);
484 return PyObject_RichCompare(proxy, v, op);
Fred Drake8844d522001-10-05 21:52:26 +0000485}
486
487/* number slots */
488WRAP_BINARY(proxy_add, PyNumber_Add)
489WRAP_BINARY(proxy_sub, PyNumber_Subtract)
490WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000491WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
492WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000493WRAP_BINARY(proxy_mod, PyNumber_Remainder)
494WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
495WRAP_TERNARY(proxy_pow, PyNumber_Power)
496WRAP_UNARY(proxy_neg, PyNumber_Negative)
497WRAP_UNARY(proxy_pos, PyNumber_Positive)
498WRAP_UNARY(proxy_abs, PyNumber_Absolute)
499WRAP_UNARY(proxy_invert, PyNumber_Invert)
500WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
501WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
502WRAP_BINARY(proxy_and, PyNumber_And)
503WRAP_BINARY(proxy_xor, PyNumber_Xor)
504WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000505WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000506WRAP_UNARY(proxy_float, PyNumber_Float)
507WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
508WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
509WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000510WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
511WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000512WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
513WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
514WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
515WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
516WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
517WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
518WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000519WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000520
Tim Peters403a2032003-11-20 21:21:46 +0000521static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000522proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000523{
524 PyObject *o = PyWeakref_GET_OBJECT(proxy);
525 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000526 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000527 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000528}
529
Fred Drake0a4dd392004-07-02 18:57:45 +0000530static void
531proxy_dealloc(PyWeakReference *self)
532{
533 if (self->wr_callback != NULL)
534 PyObject_GC_UnTrack((PyObject *)self);
535 clear_weakref(self);
536 PyObject_GC_Del(self);
537}
538
Fred Drake8844d522001-10-05 21:52:26 +0000539/* sequence slots */
540
Fred Drake8844d522001-10-05 21:52:26 +0000541static int
542proxy_contains(PyWeakReference *proxy, PyObject *value)
543{
544 if (!proxy_checkref(proxy))
545 return -1;
546 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
547}
548
549
550/* mapping slots */
551
Martin v. Löwis18e16552006-02-15 17:27:45 +0000552static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000553proxy_length(PyWeakReference *proxy)
554{
555 if (!proxy_checkref(proxy))
556 return -1;
557 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
558}
559
560WRAP_BINARY(proxy_getitem, PyObject_GetItem)
561
562static int
563proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
564{
565 if (!proxy_checkref(proxy))
566 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000567
568 if (value == NULL)
569 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
570 else
571 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000572}
573
Fred Drakef16c3dc2002-08-09 18:34:16 +0000574/* iterator slots */
575
576static PyObject *
577proxy_iter(PyWeakReference *proxy)
578{
579 if (!proxy_checkref(proxy))
580 return NULL;
581 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
582}
583
584static PyObject *
585proxy_iternext(PyWeakReference *proxy)
586{
587 if (!proxy_checkref(proxy))
588 return NULL;
589 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
590}
591
Fred Drake8844d522001-10-05 21:52:26 +0000592
Victor Stinner3e2b7172010-11-09 09:32:19 +0000593WRAP_METHOD(proxy_bytes, "__bytes__")
Benjamin Peterson32019772009-11-19 03:08:32 +0000594
595
596static PyMethodDef proxy_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000597 {"__bytes__", (PyCFunction)proxy_bytes, METH_NOARGS},
598 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000599};
600
601
Fred Drake8844d522001-10-05 21:52:26 +0000602static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000603 proxy_add, /*nb_add*/
604 proxy_sub, /*nb_subtract*/
605 proxy_mul, /*nb_multiply*/
606 proxy_mod, /*nb_remainder*/
607 proxy_divmod, /*nb_divmod*/
608 proxy_pow, /*nb_power*/
609 proxy_neg, /*nb_negative*/
610 proxy_pos, /*nb_positive*/
611 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000612 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000613 proxy_invert, /*nb_invert*/
614 proxy_lshift, /*nb_lshift*/
615 proxy_rshift, /*nb_rshift*/
616 proxy_and, /*nb_and*/
617 proxy_xor, /*nb_xor*/
618 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000619 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000620 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000621 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000622 proxy_iadd, /*nb_inplace_add*/
623 proxy_isub, /*nb_inplace_subtract*/
624 proxy_imul, /*nb_inplace_multiply*/
625 proxy_imod, /*nb_inplace_remainder*/
626 proxy_ipow, /*nb_inplace_power*/
627 proxy_ilshift, /*nb_inplace_lshift*/
628 proxy_irshift, /*nb_inplace_rshift*/
629 proxy_iand, /*nb_inplace_and*/
630 proxy_ixor, /*nb_inplace_xor*/
631 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000632 proxy_floor_div, /*nb_floor_divide*/
633 proxy_true_div, /*nb_true_divide*/
634 proxy_ifloor_div, /*nb_inplace_floor_divide*/
635 proxy_itrue_div, /*nb_inplace_true_divide*/
636 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000637};
638
639static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000640 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000641 0, /*sq_concat*/
642 0, /*sq_repeat*/
643 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000644 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000645 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000647 (objobjproc)proxy_contains, /* sq_contains */
648};
649
650static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000651 (lenfunc)proxy_length, /*mp_length*/
652 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000653 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
654};
655
656
657PyTypeObject
658_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000659 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000660 "weakproxy",
661 sizeof(PyWeakReference),
662 0,
663 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000664 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000665 0, /* tp_print */
666 0, /* tp_getattr */
667 0, /* tp_setattr */
668 0, /* tp_reserved */
669 (reprfunc)proxy_repr, /* tp_repr */
670 &proxy_as_number, /* tp_as_number */
671 &proxy_as_sequence, /* tp_as_sequence */
672 &proxy_as_mapping, /* tp_as_mapping */
673 0, /* tp_hash */
674 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000675 proxy_str, /* tp_str */
676 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000677 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000679 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000680 0, /* tp_doc */
681 (traverseproc)gc_traverse, /* tp_traverse */
682 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000683 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000684 0, /* tp_weaklistoffset */
685 (getiterfunc)proxy_iter, /* tp_iter */
686 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000688};
689
690
691PyTypeObject
692_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000693 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000694 "weakcallableproxy",
695 sizeof(PyWeakReference),
696 0,
697 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000698 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000699 0, /* tp_print */
700 0, /* tp_getattr */
701 0, /* tp_setattr */
702 0, /* tp_reserved */
703 (unaryfunc)proxy_repr, /* tp_repr */
704 &proxy_as_number, /* tp_as_number */
705 &proxy_as_sequence, /* tp_as_sequence */
706 &proxy_as_mapping, /* tp_as_mapping */
707 0, /* tp_hash */
708 proxy_call, /* tp_call */
709 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000710 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000711 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000713 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000714 0, /* tp_doc */
715 (traverseproc)gc_traverse, /* tp_traverse */
716 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000717 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000718 0, /* tp_weaklistoffset */
719 (getiterfunc)proxy_iter, /* tp_iter */
720 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000721};
722
723
Fred Drake8844d522001-10-05 21:52:26 +0000724
725PyObject *
726PyWeakref_NewRef(PyObject *ob, PyObject *callback)
727{
728 PyWeakReference *result = NULL;
729 PyWeakReference **list;
730 PyWeakReference *ref, *proxy;
731
Christian Heimes90aa7642007-12-19 02:45:37 +0000732 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000733 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000734 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000735 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000736 return NULL;
737 }
738 list = GET_WEAKREFS_LISTPTR(ob);
739 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000740 if (callback == Py_None)
741 callback = NULL;
742 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000743 /* return existing weak reference if it exists */
744 result = ref;
745 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000746 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000747 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000748 /* Note: new_weakref() can trigger cyclic GC, so the weakref
749 list on ob can be mutated. This means that the ref and
750 proxy pointers we got back earlier may have been collected,
751 so we need to compute these values again before we use
752 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000753 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000754 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000755 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000756 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000757 if (ref == NULL)
758 insert_head(result, list);
759 else {
760 /* Someone else added a ref without a callback
761 during GC. Return that one instead of this one
762 to avoid violating the invariants of the list
763 of weakrefs for ob. */
764 Py_DECREF(result);
765 Py_INCREF(ref);
766 result = ref;
767 }
Fred Drake8844d522001-10-05 21:52:26 +0000768 }
769 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000770 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000771
Fred Drakebc875f52004-02-04 23:14:14 +0000772 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000773 if (prev == NULL)
774 insert_head(result, list);
775 else
776 insert_after(result, prev);
777 }
Fred Drake8844d522001-10-05 21:52:26 +0000778 }
779 }
780 return (PyObject *) result;
781}
782
783
784PyObject *
785PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
786{
787 PyWeakReference *result = NULL;
788 PyWeakReference **list;
789 PyWeakReference *ref, *proxy;
790
Christian Heimes90aa7642007-12-19 02:45:37 +0000791 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000792 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000793 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000794 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000795 return NULL;
796 }
797 list = GET_WEAKREFS_LISTPTR(ob);
798 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000799 if (callback == Py_None)
800 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000801 if (callback == NULL)
802 /* attempt to return an existing weak reference if it exists */
803 result = proxy;
804 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000805 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000806 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000807 /* Note: new_weakref() can trigger cyclic GC, so the weakref
808 list on ob can be mutated. This means that the ref and
809 proxy pointers we got back earlier may have been collected,
810 so we need to compute these values again before we use
811 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000812 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000813 if (result != NULL) {
814 PyWeakReference *prev;
815
816 if (PyCallable_Check(ob))
Christian Heimes90aa7642007-12-19 02:45:37 +0000817 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000818 else
Christian Heimes90aa7642007-12-19 02:45:37 +0000819 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000820 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000821 if (callback == NULL) {
822 if (proxy != NULL) {
823 /* Someone else added a proxy without a callback
824 during GC. Return that one instead of this one
825 to avoid violating the invariants of the list
826 of weakrefs for ob. */
827 Py_DECREF(result);
828 Py_INCREF(result = proxy);
829 goto skip_insert;
830 }
Fred Drake8844d522001-10-05 21:52:26 +0000831 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000832 }
Fred Drake8844d522001-10-05 21:52:26 +0000833 else
834 prev = (proxy == NULL) ? ref : proxy;
835
836 if (prev == NULL)
837 insert_head(result, list);
838 else
839 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000840 skip_insert:
841 ;
Fred Drake8844d522001-10-05 21:52:26 +0000842 }
843 }
844 return (PyObject *) result;
845}
846
847
848PyObject *
849PyWeakref_GetObject(PyObject *ref)
850{
851 if (ref == NULL || !PyWeakref_Check(ref)) {
852 PyErr_BadInternalCall();
853 return NULL;
854 }
855 return PyWeakref_GET_OBJECT(ref);
856}
857
Tim Petersead8b7a2004-10-30 23:09:22 +0000858/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
859 * handle_weakrefs().
860 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000861static void
862handle_callback(PyWeakReference *ref, PyObject *callback)
863{
Thomas Wouters477c8d52006-05-27 19:21:47 +0000864 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000865
866 if (cbresult == NULL)
867 PyErr_WriteUnraisable(callback);
868 else
869 Py_DECREF(cbresult);
870}
871
872/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000873 *
874 * This iterates through the weak references for 'object' and calls callbacks
875 * for those references which have one. It returns when all callbacks have
876 * been attempted.
877 */
878void
879PyObject_ClearWeakRefs(PyObject *object)
880{
881 PyWeakReference **list;
882
883 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000884 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000885 || object->ob_refcnt != 0) {
886 PyErr_BadInternalCall();
887 return;
888 }
889 list = GET_WEAKREFS_LISTPTR(object);
890 /* Remove the callback-less basic and proxy references */
891 if (*list != NULL && (*list)->wr_callback == NULL) {
892 clear_weakref(*list);
893 if (*list != NULL && (*list)->wr_callback == NULL)
894 clear_weakref(*list);
895 }
896 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000897 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000898 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000899 int restore_error = PyErr_Occurred() ? 1 : 0;
900 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000901
Fred Drakeef8ebd12001-12-10 23:44:54 +0000902 if (restore_error)
903 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000904 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000905 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000906
Fred Drakeef8ebd12001-12-10 23:44:54 +0000907 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000908 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000909 if (callback != NULL) {
Benjamin Petersona38d1562008-06-16 20:47:12 +0000910 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000911 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000912 Py_DECREF(callback);
913 }
Fred Drake8844d522001-10-05 21:52:26 +0000914 }
915 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000916 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000917 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000918
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000919 tuple = PyTuple_New(count * 2);
920 if (tuple == NULL) {
921 if (restore_error)
922 PyErr_Fetch(&err_type, &err_value, &err_tb);
923 return;
924 }
Fred Drake8844d522001-10-05 21:52:26 +0000925
926 for (i = 0; i < count; ++i) {
927 PyWeakReference *next = current->wr_next;
928
Benjamin Petersona38d1562008-06-16 20:47:12 +0000929 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000930 {
931 Py_INCREF(current);
932 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
933 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
934 }
935 else {
936 Py_DECREF(current->wr_callback);
937 }
Fred Drake8844d522001-10-05 21:52:26 +0000938 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000939 clear_weakref(current);
940 current = next;
941 }
942 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000943 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000944
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000945 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000946 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000947 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
948 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000949 }
Fred Drake8844d522001-10-05 21:52:26 +0000950 }
951 Py_DECREF(tuple);
952 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000953 if (restore_error)
954 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000955 }
956}