blob: e07adb22b4138c50f1a52f36f3feabafd4824849 [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{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100159 PyObject *name, *repr;
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200160 _Py_IDENTIFIER(__name__);
Victor Stinner499dfcf2011-03-21 13:26:24 +0100161
162 if (PyWeakref_GET_OBJECT(self) == Py_None)
163 return PyUnicode_FromFormat("<weakref at %p; dead>", self);
164
Martin v. Löwis1ee1b6f2011-10-10 18:11:30 +0200165 name = _PyObject_GetAttrId(PyWeakref_GET_OBJECT(self), &PyId___name__);
Victor Stinner499dfcf2011-03-21 13:26:24 +0100166 if (name == NULL || !PyUnicode_Check(name)) {
167 if (name == NULL)
168 PyErr_Clear();
169 repr = PyUnicode_FromFormat(
170 "<weakref at %p; to '%s' at %p>",
171 self,
172 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
173 PyWeakref_GET_OBJECT(self));
Fred Drake8844d522001-10-05 21:52:26 +0000174 }
175 else {
Victor Stinner499dfcf2011-03-21 13:26:24 +0100176 repr = PyUnicode_FromFormat(
177 "<weakref at %p; to '%s' at %p (%U)>",
178 self,
179 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
180 PyWeakref_GET_OBJECT(self),
181 name);
Fred Drake8844d522001-10-05 21:52:26 +0000182 }
Victor Stinner499dfcf2011-03-21 13:26:24 +0100183 Py_XDECREF(name);
184 return repr;
Fred Drake8844d522001-10-05 21:52:26 +0000185}
186
187/* Weak references only support equality, not ordering. Two weak references
188 are equal if the underlying objects are equal. If the underlying object has
189 gone away, they are equal if they are identical. */
190
191static PyObject *
192weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
193{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000194 if ((op != Py_EQ && op != Py_NE) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 !PyWeakref_Check(self) ||
196 !PyWeakref_Check(other)) {
Brian Curtindfc80e32011-08-10 20:28:54 -0500197 Py_RETURN_NOTIMPLEMENTED;
Fred Drake8844d522001-10-05 21:52:26 +0000198 }
199 if (PyWeakref_GET_OBJECT(self) == Py_None
200 || PyWeakref_GET_OBJECT(other) == Py_None) {
201 PyObject *res = self==other ? Py_True : Py_False;
202 Py_INCREF(res);
203 return res;
204 }
205 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
206 PyWeakref_GET_OBJECT(other), op);
207}
208
Fred Drake0a4dd392004-07-02 18:57:45 +0000209/* Given the head of an object's list of weak references, extract the
210 * two callback-less refs (ref and proxy). Used to determine if the
211 * shared references exist and to determine the back link for newly
212 * inserted references.
213 */
214static void
215get_basic_refs(PyWeakReference *head,
216 PyWeakReference **refp, PyWeakReference **proxyp)
217{
218 *refp = NULL;
219 *proxyp = NULL;
220
221 if (head != NULL && head->wr_callback == NULL) {
222 /* We need to be careful that the "basic refs" aren't
223 subclasses of the main types. That complicates this a
224 little. */
225 if (PyWeakref_CheckRefExact(head)) {
226 *refp = head;
227 head = head->wr_next;
228 }
229 if (head != NULL
230 && head->wr_callback == NULL
231 && PyWeakref_CheckProxy(head)) {
232 *proxyp = head;
233 /* head = head->wr_next; */
234 }
235 }
236}
237
238/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
239static void
240insert_after(PyWeakReference *newref, PyWeakReference *prev)
241{
242 newref->wr_prev = prev;
243 newref->wr_next = prev->wr_next;
244 if (prev->wr_next != NULL)
245 prev->wr_next->wr_prev = newref;
246 prev->wr_next = newref;
247}
248
249/* Insert 'newref' at the head of the list; 'list' points to the variable
250 * that stores the head.
251 */
252static void
253insert_head(PyWeakReference *newref, PyWeakReference **list)
254{
255 PyWeakReference *next = *list;
256
257 newref->wr_prev = NULL;
258 newref->wr_next = next;
259 if (next != NULL)
260 next->wr_prev = newref;
261 *list = newref;
262}
263
264static int
265parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
266 PyObject **obp, PyObject **callbackp)
267{
268 /* XXX Should check that kwargs == NULL or is empty. */
269 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
270}
271
272static PyObject *
273weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
274{
275 PyWeakReference *self = NULL;
276 PyObject *ob, *callback = NULL;
277
278 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
279 PyWeakReference *ref, *proxy;
280 PyWeakReference **list;
281
Christian Heimes90aa7642007-12-19 02:45:37 +0000282 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000283 PyErr_Format(PyExc_TypeError,
284 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000285 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000286 return NULL;
287 }
288 if (callback == Py_None)
289 callback = NULL;
290 list = GET_WEAKREFS_LISTPTR(ob);
291 get_basic_refs(*list, &ref, &proxy);
292 if (callback == NULL && type == &_PyWeakref_RefType) {
293 if (ref != NULL) {
294 /* We can re-use an existing reference. */
295 Py_INCREF(ref);
296 return (PyObject *)ref;
297 }
298 }
299 /* We have to create a new reference. */
300 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
301 list on ob can be mutated. This means that the ref and
302 proxy pointers we got back earlier may have been collected,
303 so we need to compute these values again before we use
304 them. */
305 self = (PyWeakReference *) (type->tp_alloc(type, 0));
306 if (self != NULL) {
307 init_weakref(self, ob, callback);
308 if (callback == NULL && type == &_PyWeakref_RefType) {
309 insert_head(self, list);
310 }
311 else {
312 PyWeakReference *prev;
313
314 get_basic_refs(*list, &ref, &proxy);
315 prev = (proxy == NULL) ? ref : proxy;
316 if (prev == NULL)
317 insert_head(self, list);
318 else
319 insert_after(self, prev);
320 }
321 }
322 }
323 return (PyObject *)self;
324}
325
326static int
327weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
328{
329 PyObject *tmp;
330
331 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
332 return 0;
333 else
Benjamin Peterson9aa42992008-09-10 21:57:34 +0000334 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000335}
336
Fred Drake8844d522001-10-05 21:52:26 +0000337
338PyTypeObject
339_PyWeakref_RefType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000340 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000341 "weakref",
342 sizeof(PyWeakReference),
343 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000344 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000345 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000346 0, /*tp_getattr*/
347 0, /*tp_setattr*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000348 0, /*tp_reserved*/
Fred Drake8844d522001-10-05 21:52:26 +0000349 (reprfunc)weakref_repr, /*tp_repr*/
350 0, /*tp_as_number*/
351 0, /*tp_as_sequence*/
352 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000353 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000354 (ternaryfunc)weakref_call, /*tp_call*/
355 0, /*tp_str*/
356 0, /*tp_getattro*/
357 0, /*tp_setattro*/
358 0, /*tp_as_buffer*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000359 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000360 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000361 0, /*tp_doc*/
362 (traverseproc)gc_traverse, /*tp_traverse*/
363 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000364 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000365 0, /*tp_weaklistoffset*/
366 0, /*tp_iter*/
367 0, /*tp_iternext*/
368 0, /*tp_methods*/
369 0, /*tp_members*/
370 0, /*tp_getset*/
371 0, /*tp_base*/
372 0, /*tp_dict*/
373 0, /*tp_descr_get*/
374 0, /*tp_descr_set*/
375 0, /*tp_dictoffset*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000376 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000377 PyType_GenericAlloc, /*tp_alloc*/
378 weakref___new__, /*tp_new*/
379 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000380};
381
382
383static int
384proxy_checkref(PyWeakReference *proxy)
385{
386 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
387 PyErr_SetString(PyExc_ReferenceError,
388 "weakly-referenced object no longer exists");
389 return 0;
390 }
391 return 1;
392}
393
394
Fred Drake73006d02001-10-18 18:04:18 +0000395/* If a parameter is a proxy, check that it is still "live" and wrap it,
396 * replacing the original value with the raw object. Raises ReferenceError
397 * if the param is a dead proxy.
398 */
399#define UNWRAP(o) \
400 if (PyWeakref_CheckProxy(o)) { \
401 if (!proxy_checkref((PyWeakReference *)o)) \
402 return NULL; \
403 o = PyWeakref_GET_OBJECT(o); \
404 }
405
Fred Drake2a908f62001-12-19 16:44:30 +0000406#define UNWRAP_I(o) \
407 if (PyWeakref_CheckProxy(o)) { \
408 if (!proxy_checkref((PyWeakReference *)o)) \
409 return -1; \
410 o = PyWeakref_GET_OBJECT(o); \
411 }
412
Fred Drake8844d522001-10-05 21:52:26 +0000413#define WRAP_UNARY(method, generic) \
414 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000415 method(PyObject *proxy) { \
416 UNWRAP(proxy); \
417 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000418 }
419
420#define WRAP_BINARY(method, generic) \
421 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000422 method(PyObject *x, PyObject *y) { \
423 UNWRAP(x); \
424 UNWRAP(y); \
425 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000426 }
427
Fred Drake31f4d1f2001-10-18 19:21:46 +0000428/* Note that the third arg needs to be checked for NULL since the tp_call
429 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000430 */
Fred Drake8844d522001-10-05 21:52:26 +0000431#define WRAP_TERNARY(method, generic) \
432 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000433 method(PyObject *proxy, PyObject *v, PyObject *w) { \
434 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000435 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000436 if (w != NULL) \
437 UNWRAP(w); \
438 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000439 }
440
Benjamin Peterson32019772009-11-19 03:08:32 +0000441#define WRAP_METHOD(method, special) \
442 static PyObject * \
443 method(PyObject *proxy) { \
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200444 _Py_IDENTIFIER(special); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000445 UNWRAP(proxy); \
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200446 return _PyObject_CallMethodId(proxy, &PyId_##special, ""); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000447 }
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{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100459 return PyUnicode_FromFormat(
460 "<weakproxy at %p to %s at %p>",
461 proxy,
462 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
463 PyWeakref_GET_OBJECT(proxy));
Fred Drake8844d522001-10-05 21:52:26 +0000464}
465
466
467static int
468proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
469{
470 if (!proxy_checkref(proxy))
471 return -1;
472 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
473}
474
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000475static PyObject *
476proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000477{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000478 UNWRAP(proxy);
479 UNWRAP(v);
480 return PyObject_RichCompare(proxy, v, op);
Fred Drake8844d522001-10-05 21:52:26 +0000481}
482
483/* number slots */
484WRAP_BINARY(proxy_add, PyNumber_Add)
485WRAP_BINARY(proxy_sub, PyNumber_Subtract)
486WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000487WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
488WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000489WRAP_BINARY(proxy_mod, PyNumber_Remainder)
490WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
491WRAP_TERNARY(proxy_pow, PyNumber_Power)
492WRAP_UNARY(proxy_neg, PyNumber_Negative)
493WRAP_UNARY(proxy_pos, PyNumber_Positive)
494WRAP_UNARY(proxy_abs, PyNumber_Absolute)
495WRAP_UNARY(proxy_invert, PyNumber_Invert)
496WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
497WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
498WRAP_BINARY(proxy_and, PyNumber_And)
499WRAP_BINARY(proxy_xor, PyNumber_Xor)
500WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000501WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000502WRAP_UNARY(proxy_float, PyNumber_Float)
503WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
504WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
505WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000506WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
507WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000508WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
509WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
510WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
511WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
512WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
513WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
514WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000515WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000516
Tim Peters403a2032003-11-20 21:21:46 +0000517static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000518proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000519{
520 PyObject *o = PyWeakref_GET_OBJECT(proxy);
521 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000522 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000523 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000524}
525
Fred Drake0a4dd392004-07-02 18:57:45 +0000526static void
527proxy_dealloc(PyWeakReference *self)
528{
529 if (self->wr_callback != NULL)
530 PyObject_GC_UnTrack((PyObject *)self);
531 clear_weakref(self);
532 PyObject_GC_Del(self);
533}
534
Fred Drake8844d522001-10-05 21:52:26 +0000535/* sequence slots */
536
Fred Drake8844d522001-10-05 21:52:26 +0000537static int
538proxy_contains(PyWeakReference *proxy, PyObject *value)
539{
540 if (!proxy_checkref(proxy))
541 return -1;
542 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
543}
544
545
546/* mapping slots */
547
Martin v. Löwis18e16552006-02-15 17:27:45 +0000548static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000549proxy_length(PyWeakReference *proxy)
550{
551 if (!proxy_checkref(proxy))
552 return -1;
553 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
554}
555
556WRAP_BINARY(proxy_getitem, PyObject_GetItem)
557
558static int
559proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
560{
561 if (!proxy_checkref(proxy))
562 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000563
564 if (value == NULL)
565 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
566 else
567 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000568}
569
Fred Drakef16c3dc2002-08-09 18:34:16 +0000570/* iterator slots */
571
572static PyObject *
573proxy_iter(PyWeakReference *proxy)
574{
575 if (!proxy_checkref(proxy))
576 return NULL;
577 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
578}
579
580static PyObject *
581proxy_iternext(PyWeakReference *proxy)
582{
583 if (!proxy_checkref(proxy))
584 return NULL;
585 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
586}
587
Fred Drake8844d522001-10-05 21:52:26 +0000588
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200589WRAP_METHOD(proxy_bytes, __bytes__)
Benjamin Peterson32019772009-11-19 03:08:32 +0000590
591
592static PyMethodDef proxy_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 {"__bytes__", (PyCFunction)proxy_bytes, METH_NOARGS},
594 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000595};
596
597
Fred Drake8844d522001-10-05 21:52:26 +0000598static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000599 proxy_add, /*nb_add*/
600 proxy_sub, /*nb_subtract*/
601 proxy_mul, /*nb_multiply*/
602 proxy_mod, /*nb_remainder*/
603 proxy_divmod, /*nb_divmod*/
604 proxy_pow, /*nb_power*/
605 proxy_neg, /*nb_negative*/
606 proxy_pos, /*nb_positive*/
607 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000608 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000609 proxy_invert, /*nb_invert*/
610 proxy_lshift, /*nb_lshift*/
611 proxy_rshift, /*nb_rshift*/
612 proxy_and, /*nb_and*/
613 proxy_xor, /*nb_xor*/
614 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000615 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000616 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000617 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000618 proxy_iadd, /*nb_inplace_add*/
619 proxy_isub, /*nb_inplace_subtract*/
620 proxy_imul, /*nb_inplace_multiply*/
621 proxy_imod, /*nb_inplace_remainder*/
622 proxy_ipow, /*nb_inplace_power*/
623 proxy_ilshift, /*nb_inplace_lshift*/
624 proxy_irshift, /*nb_inplace_rshift*/
625 proxy_iand, /*nb_inplace_and*/
626 proxy_ixor, /*nb_inplace_xor*/
627 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000628 proxy_floor_div, /*nb_floor_divide*/
629 proxy_true_div, /*nb_true_divide*/
630 proxy_ifloor_div, /*nb_inplace_floor_divide*/
631 proxy_itrue_div, /*nb_inplace_true_divide*/
632 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000633};
634
635static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000636 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000637 0, /*sq_concat*/
638 0, /*sq_repeat*/
639 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000640 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000641 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000643 (objobjproc)proxy_contains, /* sq_contains */
644};
645
646static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000647 (lenfunc)proxy_length, /*mp_length*/
648 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000649 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
650};
651
652
653PyTypeObject
654_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000655 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000656 "weakproxy",
657 sizeof(PyWeakReference),
658 0,
659 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000660 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 0, /* tp_print */
662 0, /* tp_getattr */
663 0, /* tp_setattr */
664 0, /* tp_reserved */
665 (reprfunc)proxy_repr, /* tp_repr */
666 &proxy_as_number, /* tp_as_number */
667 &proxy_as_sequence, /* tp_as_sequence */
668 &proxy_as_mapping, /* tp_as_mapping */
669 0, /* tp_hash */
670 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000671 proxy_str, /* tp_str */
672 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000673 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000675 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000676 0, /* tp_doc */
677 (traverseproc)gc_traverse, /* tp_traverse */
678 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000679 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000680 0, /* tp_weaklistoffset */
681 (getiterfunc)proxy_iter, /* tp_iter */
682 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000684};
685
686
687PyTypeObject
688_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000689 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000690 "weakcallableproxy",
691 sizeof(PyWeakReference),
692 0,
693 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000694 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 0, /* tp_print */
696 0, /* tp_getattr */
697 0, /* tp_setattr */
698 0, /* tp_reserved */
699 (unaryfunc)proxy_repr, /* tp_repr */
700 &proxy_as_number, /* tp_as_number */
701 &proxy_as_sequence, /* tp_as_sequence */
702 &proxy_as_mapping, /* tp_as_mapping */
703 0, /* tp_hash */
704 proxy_call, /* tp_call */
705 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000706 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000707 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000709 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000710 0, /* tp_doc */
711 (traverseproc)gc_traverse, /* tp_traverse */
712 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000713 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000714 0, /* tp_weaklistoffset */
715 (getiterfunc)proxy_iter, /* tp_iter */
716 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000717};
718
719
Fred Drake8844d522001-10-05 21:52:26 +0000720
721PyObject *
722PyWeakref_NewRef(PyObject *ob, PyObject *callback)
723{
724 PyWeakReference *result = NULL;
725 PyWeakReference **list;
726 PyWeakReference *ref, *proxy;
727
Christian Heimes90aa7642007-12-19 02:45:37 +0000728 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000729 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000731 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000732 return NULL;
733 }
734 list = GET_WEAKREFS_LISTPTR(ob);
735 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000736 if (callback == Py_None)
737 callback = NULL;
738 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000739 /* return existing weak reference if it exists */
740 result = ref;
741 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000742 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000743 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000744 /* Note: new_weakref() can trigger cyclic GC, so the weakref
745 list on ob can be mutated. This means that the ref and
746 proxy pointers we got back earlier may have been collected,
747 so we need to compute these values again before we use
748 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000749 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000750 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000751 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000752 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000753 if (ref == NULL)
754 insert_head(result, list);
755 else {
756 /* Someone else added a ref without a callback
757 during GC. Return that one instead of this one
758 to avoid violating the invariants of the list
759 of weakrefs for ob. */
760 Py_DECREF(result);
761 Py_INCREF(ref);
762 result = ref;
763 }
Fred Drake8844d522001-10-05 21:52:26 +0000764 }
765 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000766 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000767
Fred Drakebc875f52004-02-04 23:14:14 +0000768 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000769 if (prev == NULL)
770 insert_head(result, list);
771 else
772 insert_after(result, prev);
773 }
Fred Drake8844d522001-10-05 21:52:26 +0000774 }
775 }
776 return (PyObject *) result;
777}
778
779
780PyObject *
781PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
782{
783 PyWeakReference *result = NULL;
784 PyWeakReference **list;
785 PyWeakReference *ref, *proxy;
786
Christian Heimes90aa7642007-12-19 02:45:37 +0000787 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000788 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000789 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000790 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000791 return NULL;
792 }
793 list = GET_WEAKREFS_LISTPTR(ob);
794 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000795 if (callback == Py_None)
796 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000797 if (callback == NULL)
798 /* attempt to return an existing weak reference if it exists */
799 result = proxy;
800 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000801 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000802 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000803 /* Note: new_weakref() can trigger cyclic GC, so the weakref
804 list on ob can be mutated. This means that the ref and
805 proxy pointers we got back earlier may have been collected,
806 so we need to compute these values again before we use
807 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000808 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000809 if (result != NULL) {
810 PyWeakReference *prev;
811
812 if (PyCallable_Check(ob))
Christian Heimes90aa7642007-12-19 02:45:37 +0000813 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000814 else
Christian Heimes90aa7642007-12-19 02:45:37 +0000815 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000816 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000817 if (callback == NULL) {
818 if (proxy != NULL) {
819 /* Someone else added a proxy without a callback
820 during GC. Return that one instead of this one
821 to avoid violating the invariants of the list
822 of weakrefs for ob. */
823 Py_DECREF(result);
824 Py_INCREF(result = proxy);
825 goto skip_insert;
826 }
Fred Drake8844d522001-10-05 21:52:26 +0000827 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000828 }
Fred Drake8844d522001-10-05 21:52:26 +0000829 else
830 prev = (proxy == NULL) ? ref : proxy;
831
832 if (prev == NULL)
833 insert_head(result, list);
834 else
835 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000836 skip_insert:
837 ;
Fred Drake8844d522001-10-05 21:52:26 +0000838 }
839 }
840 return (PyObject *) result;
841}
842
843
844PyObject *
845PyWeakref_GetObject(PyObject *ref)
846{
847 if (ref == NULL || !PyWeakref_Check(ref)) {
848 PyErr_BadInternalCall();
849 return NULL;
850 }
851 return PyWeakref_GET_OBJECT(ref);
852}
853
Tim Petersead8b7a2004-10-30 23:09:22 +0000854/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
855 * handle_weakrefs().
856 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000857static void
858handle_callback(PyWeakReference *ref, PyObject *callback)
859{
Thomas Wouters477c8d52006-05-27 19:21:47 +0000860 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000861
862 if (cbresult == NULL)
863 PyErr_WriteUnraisable(callback);
864 else
865 Py_DECREF(cbresult);
866}
867
868/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000869 *
870 * This iterates through the weak references for 'object' and calls callbacks
871 * for those references which have one. It returns when all callbacks have
872 * been attempted.
873 */
874void
875PyObject_ClearWeakRefs(PyObject *object)
876{
877 PyWeakReference **list;
878
879 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000880 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000881 || object->ob_refcnt != 0) {
882 PyErr_BadInternalCall();
883 return;
884 }
885 list = GET_WEAKREFS_LISTPTR(object);
886 /* Remove the callback-less basic and proxy references */
887 if (*list != NULL && (*list)->wr_callback == NULL) {
888 clear_weakref(*list);
889 if (*list != NULL && (*list)->wr_callback == NULL)
890 clear_weakref(*list);
891 }
892 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000893 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000894 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000895 int restore_error = PyErr_Occurred() ? 1 : 0;
896 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000897
Fred Drakeef8ebd12001-12-10 23:44:54 +0000898 if (restore_error)
899 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000900 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000901 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000902
Fred Drakeef8ebd12001-12-10 23:44:54 +0000903 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000904 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000905 if (callback != NULL) {
Benjamin Petersona38d1562008-06-16 20:47:12 +0000906 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000907 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000908 Py_DECREF(callback);
909 }
Fred Drake8844d522001-10-05 21:52:26 +0000910 }
911 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000912 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000913 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000915 tuple = PyTuple_New(count * 2);
916 if (tuple == NULL) {
917 if (restore_error)
918 PyErr_Fetch(&err_type, &err_value, &err_tb);
919 return;
920 }
Fred Drake8844d522001-10-05 21:52:26 +0000921
922 for (i = 0; i < count; ++i) {
923 PyWeakReference *next = current->wr_next;
924
Benjamin Petersona38d1562008-06-16 20:47:12 +0000925 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000926 {
927 Py_INCREF(current);
928 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
929 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
930 }
931 else {
932 Py_DECREF(current->wr_callback);
933 }
Fred Drake8844d522001-10-05 21:52:26 +0000934 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000935 clear_weakref(current);
936 current = next;
937 }
938 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000939 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000940
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000941 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000942 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000943 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
944 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000945 }
Fred Drake8844d522001-10-05 21:52:26 +0000946 }
947 Py_DECREF(tuple);
948 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000949 if (restore_error)
950 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000951 }
952}