blob: dae3c24f4a33895bc5b014169f23030dd01b4556 [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);
Barry Warsawd5867562001-11-28 21:01:56 +0000171 PyOS_snprintf(buffer, sizeof(buffer),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 name ? "<weakref at %p; to '%.50s' at %p (%s)>"
173 : "<weakref at %p; to '%.50s' at %p>",
174 self,
175 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
176 PyWeakref_GET_OBJECT(self),
177 name);
178 Py_XDECREF(nameobj);
Fred Drake8844d522001-10-05 21:52:26 +0000179 }
Walter Dörwald1ab83302007-05-18 17:15:44 +0000180 return PyUnicode_FromString(buffer);
Fred Drake8844d522001-10-05 21:52:26 +0000181}
182
183/* Weak references only support equality, not ordering. Two weak references
184 are equal if the underlying objects are equal. If the underlying object has
185 gone away, they are equal if they are identical. */
186
187static PyObject *
188weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
189{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000190 if ((op != Py_EQ && op != Py_NE) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000191 !PyWeakref_Check(self) ||
192 !PyWeakref_Check(other)) {
Fred Drake8844d522001-10-05 21:52:26 +0000193 Py_INCREF(Py_NotImplemented);
194 return Py_NotImplemented;
195 }
196 if (PyWeakref_GET_OBJECT(self) == Py_None
197 || PyWeakref_GET_OBJECT(other) == Py_None) {
Antoine Pitroue11fecb2012-11-11 19:36:51 +0100198 int res = (self == other);
199 if (op == Py_NE)
200 res = !res;
201 if (res)
202 Py_RETURN_TRUE;
203 else
204 Py_RETURN_FALSE;
Fred Drake8844d522001-10-05 21:52:26 +0000205 }
206 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
207 PyWeakref_GET_OBJECT(other), op);
208}
209
Fred Drake0a4dd392004-07-02 18:57:45 +0000210/* Given the head of an object's list of weak references, extract the
211 * two callback-less refs (ref and proxy). Used to determine if the
212 * shared references exist and to determine the back link for newly
213 * inserted references.
214 */
215static void
216get_basic_refs(PyWeakReference *head,
217 PyWeakReference **refp, PyWeakReference **proxyp)
218{
219 *refp = NULL;
220 *proxyp = NULL;
221
222 if (head != NULL && head->wr_callback == NULL) {
223 /* We need to be careful that the "basic refs" aren't
224 subclasses of the main types. That complicates this a
225 little. */
226 if (PyWeakref_CheckRefExact(head)) {
227 *refp = head;
228 head = head->wr_next;
229 }
230 if (head != NULL
231 && head->wr_callback == NULL
232 && PyWeakref_CheckProxy(head)) {
233 *proxyp = head;
234 /* head = head->wr_next; */
235 }
236 }
237}
238
239/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
240static void
241insert_after(PyWeakReference *newref, PyWeakReference *prev)
242{
243 newref->wr_prev = prev;
244 newref->wr_next = prev->wr_next;
245 if (prev->wr_next != NULL)
246 prev->wr_next->wr_prev = newref;
247 prev->wr_next = newref;
248}
249
250/* Insert 'newref' at the head of the list; 'list' points to the variable
251 * that stores the head.
252 */
253static void
254insert_head(PyWeakReference *newref, PyWeakReference **list)
255{
256 PyWeakReference *next = *list;
257
258 newref->wr_prev = NULL;
259 newref->wr_next = next;
260 if (next != NULL)
261 next->wr_prev = newref;
262 *list = newref;
263}
264
265static int
266parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
267 PyObject **obp, PyObject **callbackp)
268{
269 /* XXX Should check that kwargs == NULL or is empty. */
270 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
271}
272
273static PyObject *
274weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
275{
276 PyWeakReference *self = NULL;
277 PyObject *ob, *callback = NULL;
278
279 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
280 PyWeakReference *ref, *proxy;
281 PyWeakReference **list;
282
Christian Heimes90aa7642007-12-19 02:45:37 +0000283 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000284 PyErr_Format(PyExc_TypeError,
285 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000286 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000287 return NULL;
288 }
289 if (callback == Py_None)
290 callback = NULL;
291 list = GET_WEAKREFS_LISTPTR(ob);
292 get_basic_refs(*list, &ref, &proxy);
293 if (callback == NULL && type == &_PyWeakref_RefType) {
294 if (ref != NULL) {
295 /* We can re-use an existing reference. */
296 Py_INCREF(ref);
297 return (PyObject *)ref;
298 }
299 }
300 /* We have to create a new reference. */
301 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
302 list on ob can be mutated. This means that the ref and
303 proxy pointers we got back earlier may have been collected,
304 so we need to compute these values again before we use
305 them. */
306 self = (PyWeakReference *) (type->tp_alloc(type, 0));
307 if (self != NULL) {
308 init_weakref(self, ob, callback);
309 if (callback == NULL && type == &_PyWeakref_RefType) {
310 insert_head(self, list);
311 }
312 else {
313 PyWeakReference *prev;
314
315 get_basic_refs(*list, &ref, &proxy);
316 prev = (proxy == NULL) ? ref : proxy;
317 if (prev == NULL)
318 insert_head(self, list);
319 else
320 insert_after(self, prev);
321 }
322 }
323 }
324 return (PyObject *)self;
325}
326
327static int
328weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
329{
330 PyObject *tmp;
331
332 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
333 return 0;
334 else
Benjamin Peterson9aa42992008-09-10 21:57:34 +0000335 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000336}
337
Fred Drake8844d522001-10-05 21:52:26 +0000338
339PyTypeObject
340_PyWeakref_RefType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000341 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000342 "weakref",
343 sizeof(PyWeakReference),
344 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000345 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000346 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000347 0, /*tp_getattr*/
348 0, /*tp_setattr*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000349 0, /*tp_reserved*/
Fred Drake8844d522001-10-05 21:52:26 +0000350 (reprfunc)weakref_repr, /*tp_repr*/
351 0, /*tp_as_number*/
352 0, /*tp_as_sequence*/
353 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000354 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000355 (ternaryfunc)weakref_call, /*tp_call*/
356 0, /*tp_str*/
357 0, /*tp_getattro*/
358 0, /*tp_setattro*/
359 0, /*tp_as_buffer*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000360 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000361 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000362 0, /*tp_doc*/
363 (traverseproc)gc_traverse, /*tp_traverse*/
364 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000365 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000366 0, /*tp_weaklistoffset*/
367 0, /*tp_iter*/
368 0, /*tp_iternext*/
369 0, /*tp_methods*/
370 0, /*tp_members*/
371 0, /*tp_getset*/
372 0, /*tp_base*/
373 0, /*tp_dict*/
374 0, /*tp_descr_get*/
375 0, /*tp_descr_set*/
376 0, /*tp_dictoffset*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000377 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000378 PyType_GenericAlloc, /*tp_alloc*/
379 weakref___new__, /*tp_new*/
380 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000381};
382
383
384static int
385proxy_checkref(PyWeakReference *proxy)
386{
387 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
388 PyErr_SetString(PyExc_ReferenceError,
389 "weakly-referenced object no longer exists");
390 return 0;
391 }
392 return 1;
393}
394
395
Fred Drake73006d02001-10-18 18:04:18 +0000396/* If a parameter is a proxy, check that it is still "live" and wrap it,
397 * replacing the original value with the raw object. Raises ReferenceError
398 * if the param is a dead proxy.
399 */
400#define UNWRAP(o) \
401 if (PyWeakref_CheckProxy(o)) { \
402 if (!proxy_checkref((PyWeakReference *)o)) \
403 return NULL; \
404 o = PyWeakref_GET_OBJECT(o); \
405 }
406
Fred Drake2a908f62001-12-19 16:44:30 +0000407#define UNWRAP_I(o) \
408 if (PyWeakref_CheckProxy(o)) { \
409 if (!proxy_checkref((PyWeakReference *)o)) \
410 return -1; \
411 o = PyWeakref_GET_OBJECT(o); \
412 }
413
Fred Drake8844d522001-10-05 21:52:26 +0000414#define WRAP_UNARY(method, generic) \
415 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000416 method(PyObject *proxy) { \
417 UNWRAP(proxy); \
418 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000419 }
420
421#define WRAP_BINARY(method, generic) \
422 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000423 method(PyObject *x, PyObject *y) { \
424 UNWRAP(x); \
425 UNWRAP(y); \
426 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000427 }
428
Fred Drake31f4d1f2001-10-18 19:21:46 +0000429/* Note that the third arg needs to be checked for NULL since the tp_call
430 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000431 */
Fred Drake8844d522001-10-05 21:52:26 +0000432#define WRAP_TERNARY(method, generic) \
433 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000434 method(PyObject *proxy, PyObject *v, PyObject *w) { \
435 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000436 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000437 if (w != NULL) \
438 UNWRAP(w); \
439 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000440 }
441
Benjamin Peterson32019772009-11-19 03:08:32 +0000442#define WRAP_METHOD(method, special) \
443 static PyObject * \
444 method(PyObject *proxy) { \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000445 UNWRAP(proxy); \
446 return PyObject_CallMethod(proxy, special, ""); \
447 }
Benjamin Peterson32019772009-11-19 03:08:32 +0000448
Fred Drake8844d522001-10-05 21:52:26 +0000449
450/* direct slots */
451
452WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
453WRAP_UNARY(proxy_str, PyObject_Str)
454WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
455
Fred Drake8844d522001-10-05 21:52:26 +0000456static PyObject *
457proxy_repr(PyWeakReference *proxy)
458{
459 char buf[160];
Barry Warsawd5867562001-11-28 21:01:56 +0000460 PyOS_snprintf(buf, sizeof(buf),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 "<weakproxy at %p to %.100s at %p>", proxy,
462 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
463 PyWeakref_GET_OBJECT(proxy));
Walter Dörwald1ab83302007-05-18 17:15:44 +0000464 return PyUnicode_FromString(buf);
Fred Drake8844d522001-10-05 21:52:26 +0000465}
466
467
468static int
469proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
470{
471 if (!proxy_checkref(proxy))
472 return -1;
473 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
474}
475
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000476static PyObject *
477proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000478{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000479 UNWRAP(proxy);
480 UNWRAP(v);
481 return PyObject_RichCompare(proxy, v, op);
Fred Drake8844d522001-10-05 21:52:26 +0000482}
483
484/* number slots */
485WRAP_BINARY(proxy_add, PyNumber_Add)
486WRAP_BINARY(proxy_sub, PyNumber_Subtract)
487WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000488WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
489WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000490WRAP_BINARY(proxy_mod, PyNumber_Remainder)
491WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
492WRAP_TERNARY(proxy_pow, PyNumber_Power)
493WRAP_UNARY(proxy_neg, PyNumber_Negative)
494WRAP_UNARY(proxy_pos, PyNumber_Positive)
495WRAP_UNARY(proxy_abs, PyNumber_Absolute)
496WRAP_UNARY(proxy_invert, PyNumber_Invert)
497WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
498WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
499WRAP_BINARY(proxy_and, PyNumber_And)
500WRAP_BINARY(proxy_xor, PyNumber_Xor)
501WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000502WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000503WRAP_UNARY(proxy_float, PyNumber_Float)
504WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
505WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
506WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000507WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
508WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000509WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
510WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
511WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
512WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
513WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
514WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
515WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000516WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000517
Tim Peters403a2032003-11-20 21:21:46 +0000518static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000519proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000520{
521 PyObject *o = PyWeakref_GET_OBJECT(proxy);
522 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000523 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000524 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000525}
526
Fred Drake0a4dd392004-07-02 18:57:45 +0000527static void
528proxy_dealloc(PyWeakReference *self)
529{
530 if (self->wr_callback != NULL)
531 PyObject_GC_UnTrack((PyObject *)self);
532 clear_weakref(self);
533 PyObject_GC_Del(self);
534}
535
Fred Drake8844d522001-10-05 21:52:26 +0000536/* sequence slots */
537
Fred Drake8844d522001-10-05 21:52:26 +0000538static int
539proxy_contains(PyWeakReference *proxy, PyObject *value)
540{
541 if (!proxy_checkref(proxy))
542 return -1;
543 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
544}
545
546
547/* mapping slots */
548
Martin v. Löwis18e16552006-02-15 17:27:45 +0000549static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000550proxy_length(PyWeakReference *proxy)
551{
552 if (!proxy_checkref(proxy))
553 return -1;
554 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
555}
556
557WRAP_BINARY(proxy_getitem, PyObject_GetItem)
558
559static int
560proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
561{
562 if (!proxy_checkref(proxy))
563 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000564
565 if (value == NULL)
566 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
567 else
568 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000569}
570
Fred Drakef16c3dc2002-08-09 18:34:16 +0000571/* iterator slots */
572
573static PyObject *
574proxy_iter(PyWeakReference *proxy)
575{
576 if (!proxy_checkref(proxy))
577 return NULL;
578 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
579}
580
581static PyObject *
582proxy_iternext(PyWeakReference *proxy)
583{
584 if (!proxy_checkref(proxy))
585 return NULL;
586 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
587}
588
Fred Drake8844d522001-10-05 21:52:26 +0000589
Victor Stinner3e2b7172010-11-09 09:32:19 +0000590WRAP_METHOD(proxy_bytes, "__bytes__")
Benjamin Peterson32019772009-11-19 03:08:32 +0000591
592
593static PyMethodDef proxy_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000594 {"__bytes__", (PyCFunction)proxy_bytes, METH_NOARGS},
595 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000596};
597
598
Fred Drake8844d522001-10-05 21:52:26 +0000599static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000600 proxy_add, /*nb_add*/
601 proxy_sub, /*nb_subtract*/
602 proxy_mul, /*nb_multiply*/
603 proxy_mod, /*nb_remainder*/
604 proxy_divmod, /*nb_divmod*/
605 proxy_pow, /*nb_power*/
606 proxy_neg, /*nb_negative*/
607 proxy_pos, /*nb_positive*/
608 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000609 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000610 proxy_invert, /*nb_invert*/
611 proxy_lshift, /*nb_lshift*/
612 proxy_rshift, /*nb_rshift*/
613 proxy_and, /*nb_and*/
614 proxy_xor, /*nb_xor*/
615 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000616 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000617 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000618 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000619 proxy_iadd, /*nb_inplace_add*/
620 proxy_isub, /*nb_inplace_subtract*/
621 proxy_imul, /*nb_inplace_multiply*/
622 proxy_imod, /*nb_inplace_remainder*/
623 proxy_ipow, /*nb_inplace_power*/
624 proxy_ilshift, /*nb_inplace_lshift*/
625 proxy_irshift, /*nb_inplace_rshift*/
626 proxy_iand, /*nb_inplace_and*/
627 proxy_ixor, /*nb_inplace_xor*/
628 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000629 proxy_floor_div, /*nb_floor_divide*/
630 proxy_true_div, /*nb_true_divide*/
631 proxy_ifloor_div, /*nb_inplace_floor_divide*/
632 proxy_itrue_div, /*nb_inplace_true_divide*/
633 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000634};
635
636static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000637 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000638 0, /*sq_concat*/
639 0, /*sq_repeat*/
640 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000641 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000642 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000644 (objobjproc)proxy_contains, /* sq_contains */
645};
646
647static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000648 (lenfunc)proxy_length, /*mp_length*/
649 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000650 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
651};
652
653
654PyTypeObject
655_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000656 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000657 "weakproxy",
658 sizeof(PyWeakReference),
659 0,
660 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000661 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 0, /* tp_print */
663 0, /* tp_getattr */
664 0, /* tp_setattr */
665 0, /* tp_reserved */
666 (reprfunc)proxy_repr, /* tp_repr */
667 &proxy_as_number, /* tp_as_number */
668 &proxy_as_sequence, /* tp_as_sequence */
669 &proxy_as_mapping, /* tp_as_mapping */
670 0, /* tp_hash */
671 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000672 proxy_str, /* tp_str */
673 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000674 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000675 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000676 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000677 0, /* tp_doc */
678 (traverseproc)gc_traverse, /* tp_traverse */
679 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000680 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000681 0, /* tp_weaklistoffset */
682 (getiterfunc)proxy_iter, /* tp_iter */
683 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000685};
686
687
688PyTypeObject
689_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000690 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000691 "weakcallableproxy",
692 sizeof(PyWeakReference),
693 0,
694 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000695 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 0, /* tp_print */
697 0, /* tp_getattr */
698 0, /* tp_setattr */
699 0, /* tp_reserved */
700 (unaryfunc)proxy_repr, /* tp_repr */
701 &proxy_as_number, /* tp_as_number */
702 &proxy_as_sequence, /* tp_as_sequence */
703 &proxy_as_mapping, /* tp_as_mapping */
704 0, /* tp_hash */
705 proxy_call, /* tp_call */
706 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000707 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000708 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000709 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000710 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000711 0, /* tp_doc */
712 (traverseproc)gc_traverse, /* tp_traverse */
713 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000714 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000715 0, /* tp_weaklistoffset */
716 (getiterfunc)proxy_iter, /* tp_iter */
717 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000718};
719
720
Fred Drake8844d522001-10-05 21:52:26 +0000721
722PyObject *
723PyWeakref_NewRef(PyObject *ob, PyObject *callback)
724{
725 PyWeakReference *result = NULL;
726 PyWeakReference **list;
727 PyWeakReference *ref, *proxy;
728
Christian Heimes90aa7642007-12-19 02:45:37 +0000729 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000730 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000731 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000732 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000733 return NULL;
734 }
735 list = GET_WEAKREFS_LISTPTR(ob);
736 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000737 if (callback == Py_None)
738 callback = NULL;
739 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000740 /* return existing weak reference if it exists */
741 result = ref;
742 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000743 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000744 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000745 /* Note: new_weakref() can trigger cyclic GC, so the weakref
746 list on ob can be mutated. This means that the ref and
747 proxy pointers we got back earlier may have been collected,
748 so we need to compute these values again before we use
749 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000750 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000751 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000752 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000753 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000754 if (ref == NULL)
755 insert_head(result, list);
756 else {
757 /* Someone else added a ref without a callback
758 during GC. Return that one instead of this one
759 to avoid violating the invariants of the list
760 of weakrefs for ob. */
761 Py_DECREF(result);
762 Py_INCREF(ref);
763 result = ref;
764 }
Fred Drake8844d522001-10-05 21:52:26 +0000765 }
766 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000767 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000768
Fred Drakebc875f52004-02-04 23:14:14 +0000769 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000770 if (prev == NULL)
771 insert_head(result, list);
772 else
773 insert_after(result, prev);
774 }
Fred Drake8844d522001-10-05 21:52:26 +0000775 }
776 }
777 return (PyObject *) result;
778}
779
780
781PyObject *
782PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
783{
784 PyWeakReference *result = NULL;
785 PyWeakReference **list;
786 PyWeakReference *ref, *proxy;
787
Christian Heimes90aa7642007-12-19 02:45:37 +0000788 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000789 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000790 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000791 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000792 return NULL;
793 }
794 list = GET_WEAKREFS_LISTPTR(ob);
795 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000796 if (callback == Py_None)
797 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000798 if (callback == NULL)
799 /* attempt to return an existing weak reference if it exists */
800 result = proxy;
801 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000802 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000803 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000804 /* Note: new_weakref() can trigger cyclic GC, so the weakref
805 list on ob can be mutated. This means that the ref and
806 proxy pointers we got back earlier may have been collected,
807 so we need to compute these values again before we use
808 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000809 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000810 if (result != NULL) {
811 PyWeakReference *prev;
812
813 if (PyCallable_Check(ob))
Christian Heimes90aa7642007-12-19 02:45:37 +0000814 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000815 else
Christian Heimes90aa7642007-12-19 02:45:37 +0000816 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000817 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000818 if (callback == NULL) {
819 if (proxy != NULL) {
820 /* Someone else added a proxy without a callback
821 during GC. Return that one instead of this one
822 to avoid violating the invariants of the list
823 of weakrefs for ob. */
824 Py_DECREF(result);
825 Py_INCREF(result = proxy);
826 goto skip_insert;
827 }
Fred Drake8844d522001-10-05 21:52:26 +0000828 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000829 }
Fred Drake8844d522001-10-05 21:52:26 +0000830 else
831 prev = (proxy == NULL) ? ref : proxy;
832
833 if (prev == NULL)
834 insert_head(result, list);
835 else
836 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000837 skip_insert:
838 ;
Fred Drake8844d522001-10-05 21:52:26 +0000839 }
840 }
841 return (PyObject *) result;
842}
843
844
845PyObject *
846PyWeakref_GetObject(PyObject *ref)
847{
848 if (ref == NULL || !PyWeakref_Check(ref)) {
849 PyErr_BadInternalCall();
850 return NULL;
851 }
852 return PyWeakref_GET_OBJECT(ref);
853}
854
Tim Petersead8b7a2004-10-30 23:09:22 +0000855/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
856 * handle_weakrefs().
857 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000858static void
859handle_callback(PyWeakReference *ref, PyObject *callback)
860{
Thomas Wouters477c8d52006-05-27 19:21:47 +0000861 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000862
863 if (cbresult == NULL)
864 PyErr_WriteUnraisable(callback);
865 else
866 Py_DECREF(cbresult);
867}
868
869/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000870 *
871 * This iterates through the weak references for 'object' and calls callbacks
872 * for those references which have one. It returns when all callbacks have
873 * been attempted.
874 */
875void
876PyObject_ClearWeakRefs(PyObject *object)
877{
878 PyWeakReference **list;
879
880 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000881 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000882 || object->ob_refcnt != 0) {
883 PyErr_BadInternalCall();
884 return;
885 }
886 list = GET_WEAKREFS_LISTPTR(object);
887 /* Remove the callback-less basic and proxy references */
888 if (*list != NULL && (*list)->wr_callback == NULL) {
889 clear_weakref(*list);
890 if (*list != NULL && (*list)->wr_callback == NULL)
891 clear_weakref(*list);
892 }
893 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000894 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000895 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000896 int restore_error = PyErr_Occurred() ? 1 : 0;
897 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000898
Fred Drakeef8ebd12001-12-10 23:44:54 +0000899 if (restore_error)
900 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000901 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000902 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000903
Fred Drakeef8ebd12001-12-10 23:44:54 +0000904 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000905 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000906 if (callback != NULL) {
Benjamin Petersona38d1562008-06-16 20:47:12 +0000907 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000908 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000909 Py_DECREF(callback);
910 }
Fred Drake8844d522001-10-05 21:52:26 +0000911 }
912 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000913 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000914 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000915
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000916 tuple = PyTuple_New(count * 2);
917 if (tuple == NULL) {
918 if (restore_error)
919 PyErr_Fetch(&err_type, &err_value, &err_tb);
920 return;
921 }
Fred Drake8844d522001-10-05 21:52:26 +0000922
923 for (i = 0; i < count; ++i) {
924 PyWeakReference *next = current->wr_next;
925
Benjamin Petersona38d1562008-06-16 20:47:12 +0000926 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000927 {
928 Py_INCREF(current);
929 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
930 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
931 }
932 else {
933 Py_DECREF(current->wr_callback);
934 }
Fred Drake8844d522001-10-05 21:52:26 +0000935 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000936 clear_weakref(current);
937 current = next;
938 }
939 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000940 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000941
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000942 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000943 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000944 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
945 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000946 }
Fred Drake8844d522001-10-05 21:52:26 +0000947 }
948 Py_DECREF(tuple);
949 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000950 if (restore_error)
951 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000952 }
953}