blob: 871c248ff2e7a4aa1041a7646d6370eea34e64b9 [file] [log] [blame]
Fred Drake8844d522001-10-05 21:52:26 +00001#include "Python.h"
2#include "structmember.h"
3
4
5#define GET_WEAKREFS_LISTPTR(o) \
6 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
7
Fred Drake8844d522001-10-05 21:52:26 +00008
Neal Norwitzc5e060d2006-08-02 06:14:22 +00009Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +000010_PyWeakref_GetWeakrefCount(PyWeakReference *head)
11{
Neal Norwitzc5e060d2006-08-02 06:14:22 +000012 Py_ssize_t count = 0;
Fred Drake8844d522001-10-05 21:52:26 +000013
14 while (head != NULL) {
15 ++count;
16 head = head->wr_next;
17 }
18 return count;
19}
20
21
Fred Drake0a4dd392004-07-02 18:57:45 +000022static void
23init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
24{
25 self->hash = -1;
26 self->wr_object = ob;
27 Py_XINCREF(callback);
28 self->wr_callback = callback;
29}
30
Fred Drake8844d522001-10-05 21:52:26 +000031static PyWeakReference *
Neil Schemenauer38a89162002-03-27 15:18:21 +000032new_weakref(PyObject *ob, PyObject *callback)
Fred Drake8844d522001-10-05 21:52:26 +000033{
34 PyWeakReference *result;
35
Neil Schemenauer38a89162002-03-27 15:18:21 +000036 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
37 if (result) {
Fred Drake0a4dd392004-07-02 18:57:45 +000038 init_weakref(result, ob, callback);
Neil Schemenauer38a89162002-03-27 15:18:21 +000039 PyObject_GC_Track(result);
40 }
Fred Drake8844d522001-10-05 21:52:26 +000041 return result;
42}
43
44
45/* This function clears the passed-in reference and removes it from the
46 * list of weak references for the referent. This is the only code that
47 * removes an item from the doubly-linked list of weak references for an
48 * object; it is also responsible for clearing the callback slot.
49 */
50static void
51clear_weakref(PyWeakReference *self)
52{
53 PyObject *callback = self->wr_callback;
54
Antoine Pitroud38c9902012-12-08 21:15:26 +010055 if (self->wr_object != Py_None) {
56 PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
Fred Drake8844d522001-10-05 21:52:26 +000057
58 if (*list == self)
Antoine Pitrouc83ea132010-05-09 14:46:46 +000059 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
60 then the weakref list itself (and thus the value of *list) will
61 end up being set to NULL. */
Fred Drake8844d522001-10-05 21:52:26 +000062 *list = self->wr_next;
63 self->wr_object = Py_None;
Fred Drake8844d522001-10-05 21:52:26 +000064 if (self->wr_prev != NULL)
65 self->wr_prev->wr_next = self->wr_next;
66 if (self->wr_next != NULL)
67 self->wr_next->wr_prev = self->wr_prev;
68 self->wr_prev = NULL;
69 self->wr_next = NULL;
Tim Peters403a2032003-11-20 21:21:46 +000070 }
71 if (callback != NULL) {
72 Py_DECREF(callback);
73 self->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +000074 }
75}
76
Tim Peters403a2032003-11-20 21:21:46 +000077/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
78 * the callback intact and uncalled. It must be possible to call self's
79 * tp_dealloc() after calling this, so self has to be left in a sane enough
80 * state for that to work. We expect tp_dealloc to decref the callback
81 * then. The reason for not letting clear_weakref() decref the callback
82 * right now is that if the callback goes away, that may in turn trigger
83 * another callback (if a weak reference to the callback exists) -- running
84 * arbitrary Python code in the middle of gc is a disaster. The convolution
85 * here allows gc to delay triggering such callbacks until the world is in
86 * a sane state again.
87 */
88void
89_PyWeakref_ClearRef(PyWeakReference *self)
90{
91 PyObject *callback;
92
93 assert(self != NULL);
94 assert(PyWeakref_Check(self));
95 /* Preserve and restore the callback around clear_weakref. */
96 callback = self->wr_callback;
97 self->wr_callback = NULL;
98 clear_weakref(self);
99 self->wr_callback = callback;
100}
Fred Drake8844d522001-10-05 21:52:26 +0000101
102static void
Fred Drake0a4dd392004-07-02 18:57:45 +0000103weakref_dealloc(PyObject *self)
Fred Drake8844d522001-10-05 21:52:26 +0000104{
Fred Drake0a4dd392004-07-02 18:57:45 +0000105 PyObject_GC_UnTrack(self);
106 clear_weakref((PyWeakReference *) self);
Christian Heimese93237d2007-12-19 02:37:44 +0000107 Py_TYPE(self)->tp_free(self);
Fred Drake8844d522001-10-05 21:52:26 +0000108}
109
110
111static int
112gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
113{
Thomas Woutersc6e55062006-04-15 21:47:09 +0000114 Py_VISIT(self->wr_callback);
Fred Drake8844d522001-10-05 21:52:26 +0000115 return 0;
116}
117
118
119static int
120gc_clear(PyWeakReference *self)
121{
122 clear_weakref(self);
123 return 0;
124}
125
126
127static PyObject *
128weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
129{
Martin v. Löwis15e62742006-02-27 16:46:16 +0000130 static char *kwlist[] = {NULL};
Fred Drake8844d522001-10-05 21:52:26 +0000131
Martin v. Löwis15e62742006-02-27 16:46:16 +0000132 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
Fred Drake8844d522001-10-05 21:52:26 +0000133 PyObject *object = PyWeakref_GET_OBJECT(self);
134 Py_INCREF(object);
135 return (object);
136 }
137 return NULL;
138}
139
140
141static long
142weakref_hash(PyWeakReference *self)
143{
144 if (self->hash != -1)
145 return self->hash;
146 if (PyWeakref_GET_OBJECT(self) == Py_None) {
147 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
148 return -1;
149 }
150 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
151 return self->hash;
152}
Tim Peters403a2032003-11-20 21:21:46 +0000153
Fred Drake8844d522001-10-05 21:52:26 +0000154
155static PyObject *
156weakref_repr(PyWeakReference *self)
157{
158 char buffer[256];
159 if (PyWeakref_GET_OBJECT(self) == Py_None) {
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000160 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
Fred Drake8844d522001-10-05 21:52:26 +0000161 }
162 else {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000163 char *name = NULL;
164 PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
165 "__name__");
166 if (nameobj == NULL)
167 PyErr_Clear();
168 else if (PyString_Check(nameobj))
169 name = PyString_AS_STRING(nameobj);
Gregory P. Smithc0022b22013-02-01 16:13:27 -0800170 if (name != NULL) {
171 PyOS_snprintf(buffer, sizeof(buffer),
172 "<weakref at %p; to '%.50s' at %p (%s)>",
173 self,
174 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
175 PyWeakref_GET_OBJECT(self),
176 name);
177 }
178 else {
179 PyOS_snprintf(buffer, sizeof(buffer),
180 "<weakref at %p; to '%.50s' at %p>",
181 self,
182 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
183 PyWeakref_GET_OBJECT(self));
184 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000185 Py_XDECREF(nameobj);
Fred Drake8844d522001-10-05 21:52:26 +0000186 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000187 return PyString_FromString(buffer);
Fred Drake8844d522001-10-05 21:52:26 +0000188}
189
190/* Weak references only support equality, not ordering. Two weak references
191 are equal if the underlying objects are equal. If the underlying object has
192 gone away, they are equal if they are identical. */
193
194static PyObject *
195weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
196{
Antoine Pitroub704eab2012-11-11 19:36:51 +0100197 if ((op != Py_EQ && op != Py_NE) || self->ob_type != other->ob_type) {
Fred Drake8844d522001-10-05 21:52:26 +0000198 Py_INCREF(Py_NotImplemented);
199 return Py_NotImplemented;
200 }
201 if (PyWeakref_GET_OBJECT(self) == Py_None
202 || PyWeakref_GET_OBJECT(other) == Py_None) {
Antoine Pitroub704eab2012-11-11 19:36:51 +0100203 int res = (self == other);
204 if (op == Py_NE)
205 res = !res;
206 if (res)
207 Py_RETURN_TRUE;
208 else
209 Py_RETURN_FALSE;
Fred Drake8844d522001-10-05 21:52:26 +0000210 }
211 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
212 PyWeakref_GET_OBJECT(other), op);
213}
214
Fred Drake0a4dd392004-07-02 18:57:45 +0000215/* Given the head of an object's list of weak references, extract the
216 * two callback-less refs (ref and proxy). Used to determine if the
217 * shared references exist and to determine the back link for newly
218 * inserted references.
219 */
220static void
221get_basic_refs(PyWeakReference *head,
222 PyWeakReference **refp, PyWeakReference **proxyp)
223{
224 *refp = NULL;
225 *proxyp = NULL;
226
227 if (head != NULL && head->wr_callback == NULL) {
228 /* We need to be careful that the "basic refs" aren't
229 subclasses of the main types. That complicates this a
230 little. */
231 if (PyWeakref_CheckRefExact(head)) {
232 *refp = head;
233 head = head->wr_next;
234 }
235 if (head != NULL
236 && head->wr_callback == NULL
237 && PyWeakref_CheckProxy(head)) {
238 *proxyp = head;
239 /* head = head->wr_next; */
240 }
241 }
242}
243
244/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
245static void
246insert_after(PyWeakReference *newref, PyWeakReference *prev)
247{
248 newref->wr_prev = prev;
249 newref->wr_next = prev->wr_next;
250 if (prev->wr_next != NULL)
251 prev->wr_next->wr_prev = newref;
252 prev->wr_next = newref;
253}
254
255/* Insert 'newref' at the head of the list; 'list' points to the variable
256 * that stores the head.
257 */
258static void
259insert_head(PyWeakReference *newref, PyWeakReference **list)
260{
261 PyWeakReference *next = *list;
262
263 newref->wr_prev = NULL;
264 newref->wr_next = next;
265 if (next != NULL)
266 next->wr_prev = newref;
267 *list = newref;
268}
269
270static int
271parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
272 PyObject **obp, PyObject **callbackp)
273{
274 /* XXX Should check that kwargs == NULL or is empty. */
275 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
276}
277
278static PyObject *
279weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
280{
281 PyWeakReference *self = NULL;
282 PyObject *ob, *callback = NULL;
283
284 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
285 PyWeakReference *ref, *proxy;
286 PyWeakReference **list;
287
Christian Heimese93237d2007-12-19 02:37:44 +0000288 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000289 PyErr_Format(PyExc_TypeError,
290 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000291 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000292 return NULL;
293 }
294 if (callback == Py_None)
295 callback = NULL;
296 list = GET_WEAKREFS_LISTPTR(ob);
297 get_basic_refs(*list, &ref, &proxy);
298 if (callback == NULL && type == &_PyWeakref_RefType) {
299 if (ref != NULL) {
300 /* We can re-use an existing reference. */
301 Py_INCREF(ref);
302 return (PyObject *)ref;
303 }
304 }
305 /* We have to create a new reference. */
306 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
307 list on ob can be mutated. This means that the ref and
308 proxy pointers we got back earlier may have been collected,
309 so we need to compute these values again before we use
310 them. */
311 self = (PyWeakReference *) (type->tp_alloc(type, 0));
312 if (self != NULL) {
313 init_weakref(self, ob, callback);
314 if (callback == NULL && type == &_PyWeakref_RefType) {
315 insert_head(self, list);
316 }
317 else {
318 PyWeakReference *prev;
319
320 get_basic_refs(*list, &ref, &proxy);
321 prev = (proxy == NULL) ? ref : proxy;
322 if (prev == NULL)
323 insert_head(self, list);
324 else
325 insert_after(self, prev);
326 }
327 }
328 }
329 return (PyObject *)self;
330}
331
332static int
333weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
334{
335 PyObject *tmp;
336
337 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
338 return 0;
339 else
Benjamin Peterson97179b02008-09-09 20:55:01 +0000340 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000341}
342
Fred Drake8844d522001-10-05 21:52:26 +0000343
344PyTypeObject
345_PyWeakref_RefType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000346 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000347 "weakref",
348 sizeof(PyWeakReference),
349 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000350 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000351 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000352 0, /*tp_getattr*/
353 0, /*tp_setattr*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000354 0, /*tp_compare*/
Fred Drake8844d522001-10-05 21:52:26 +0000355 (reprfunc)weakref_repr, /*tp_repr*/
356 0, /*tp_as_number*/
357 0, /*tp_as_sequence*/
358 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000359 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000360 (ternaryfunc)weakref_call, /*tp_call*/
361 0, /*tp_str*/
362 0, /*tp_getattro*/
363 0, /*tp_setattro*/
364 0, /*tp_as_buffer*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000365 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
366 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000367 0, /*tp_doc*/
368 (traverseproc)gc_traverse, /*tp_traverse*/
369 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000370 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000371 0, /*tp_weaklistoffset*/
372 0, /*tp_iter*/
373 0, /*tp_iternext*/
374 0, /*tp_methods*/
375 0, /*tp_members*/
376 0, /*tp_getset*/
377 0, /*tp_base*/
378 0, /*tp_dict*/
379 0, /*tp_descr_get*/
380 0, /*tp_descr_set*/
381 0, /*tp_dictoffset*/
Georg Brandl347b3002006-03-30 11:57:00 +0000382 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000383 PyType_GenericAlloc, /*tp_alloc*/
384 weakref___new__, /*tp_new*/
385 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000386};
387
388
389static int
390proxy_checkref(PyWeakReference *proxy)
391{
392 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
393 PyErr_SetString(PyExc_ReferenceError,
394 "weakly-referenced object no longer exists");
395 return 0;
396 }
397 return 1;
398}
399
400
Fred Drake73006d02001-10-18 18:04:18 +0000401/* If a parameter is a proxy, check that it is still "live" and wrap it,
402 * replacing the original value with the raw object. Raises ReferenceError
403 * if the param is a dead proxy.
404 */
405#define UNWRAP(o) \
406 if (PyWeakref_CheckProxy(o)) { \
407 if (!proxy_checkref((PyWeakReference *)o)) \
408 return NULL; \
409 o = PyWeakref_GET_OBJECT(o); \
410 }
411
Fred Drake2a908f62001-12-19 16:44:30 +0000412#define UNWRAP_I(o) \
413 if (PyWeakref_CheckProxy(o)) { \
414 if (!proxy_checkref((PyWeakReference *)o)) \
415 return -1; \
416 o = PyWeakref_GET_OBJECT(o); \
417 }
418
Fred Drake8844d522001-10-05 21:52:26 +0000419#define WRAP_UNARY(method, generic) \
420 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000421 method(PyObject *proxy) { \
422 UNWRAP(proxy); \
423 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000424 }
425
426#define WRAP_BINARY(method, generic) \
427 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000428 method(PyObject *x, PyObject *y) { \
429 UNWRAP(x); \
430 UNWRAP(y); \
431 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000432 }
433
Fred Drake31f4d1f2001-10-18 19:21:46 +0000434/* Note that the third arg needs to be checked for NULL since the tp_call
435 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000436 */
Fred Drake8844d522001-10-05 21:52:26 +0000437#define WRAP_TERNARY(method, generic) \
438 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000439 method(PyObject *proxy, PyObject *v, PyObject *w) { \
440 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000441 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000442 if (w != NULL) \
443 UNWRAP(w); \
444 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000445 }
446
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000447#define WRAP_METHOD(method, special) \
448 static PyObject * \
449 method(PyObject *proxy) { \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000450 UNWRAP(proxy); \
451 return PyObject_CallMethod(proxy, special, ""); \
452 }
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000453
Fred Drake8844d522001-10-05 21:52:26 +0000454
455/* direct slots */
456
457WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
458WRAP_UNARY(proxy_str, PyObject_Str)
459WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
460
Fred Drake8844d522001-10-05 21:52:26 +0000461static PyObject *
462proxy_repr(PyWeakReference *proxy)
463{
464 char buf[160];
Barry Warsawd5867562001-11-28 21:01:56 +0000465 PyOS_snprintf(buf, sizeof(buf),
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000466 "<weakproxy at %p to %.100s at %p>", proxy,
467 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
468 PyWeakref_GET_OBJECT(proxy));
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000469 return PyString_FromString(buf);
Fred Drake8844d522001-10-05 21:52:26 +0000470}
471
472
473static int
474proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
475{
476 if (!proxy_checkref(proxy))
477 return -1;
478 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
479}
480
481static int
Fred Drake2a908f62001-12-19 16:44:30 +0000482proxy_compare(PyObject *proxy, PyObject *v)
Fred Drake8844d522001-10-05 21:52:26 +0000483{
Fred Drake2a908f62001-12-19 16:44:30 +0000484 UNWRAP_I(proxy);
485 UNWRAP_I(v);
486 return PyObject_Compare(proxy, v);
Fred Drake8844d522001-10-05 21:52:26 +0000487}
488
489/* number slots */
490WRAP_BINARY(proxy_add, PyNumber_Add)
491WRAP_BINARY(proxy_sub, PyNumber_Subtract)
492WRAP_BINARY(proxy_mul, PyNumber_Multiply)
493WRAP_BINARY(proxy_div, PyNumber_Divide)
Georg Brandl88659b02008-05-20 08:40:43 +0000494WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
495WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000496WRAP_BINARY(proxy_mod, PyNumber_Remainder)
497WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
498WRAP_TERNARY(proxy_pow, PyNumber_Power)
499WRAP_UNARY(proxy_neg, PyNumber_Negative)
500WRAP_UNARY(proxy_pos, PyNumber_Positive)
501WRAP_UNARY(proxy_abs, PyNumber_Absolute)
502WRAP_UNARY(proxy_invert, PyNumber_Invert)
503WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
504WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
505WRAP_BINARY(proxy_and, PyNumber_And)
506WRAP_BINARY(proxy_xor, PyNumber_Xor)
507WRAP_BINARY(proxy_or, PyNumber_Or)
508WRAP_UNARY(proxy_int, PyNumber_Int)
509WRAP_UNARY(proxy_long, PyNumber_Long)
510WRAP_UNARY(proxy_float, PyNumber_Float)
511WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
512WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
513WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
514WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
Georg Brandl88659b02008-05-20 08:40:43 +0000515WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
516WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000517WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
518WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
519WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
520WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
521WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
522WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
523WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandl88659b02008-05-20 08:40:43 +0000524WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000525
Tim Peters403a2032003-11-20 21:21:46 +0000526static int
Fred Drake8844d522001-10-05 21:52:26 +0000527proxy_nonzero(PyWeakReference *proxy)
528{
529 PyObject *o = PyWeakref_GET_OBJECT(proxy);
530 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000531 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000532 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000533}
534
Fred Drake0a4dd392004-07-02 18:57:45 +0000535static void
536proxy_dealloc(PyWeakReference *self)
537{
538 if (self->wr_callback != NULL)
539 PyObject_GC_UnTrack((PyObject *)self);
540 clear_weakref(self);
541 PyObject_GC_Del(self);
542}
543
Fred Drake8844d522001-10-05 21:52:26 +0000544/* sequence slots */
545
546static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000547proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
Fred Drake8844d522001-10-05 21:52:26 +0000548{
549 if (!proxy_checkref(proxy))
550 return NULL;
551 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
552}
553
554static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000555proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
Fred Drake8844d522001-10-05 21:52:26 +0000556{
557 if (!proxy_checkref(proxy))
558 return -1;
559 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
560}
561
562static int
563proxy_contains(PyWeakReference *proxy, PyObject *value)
564{
565 if (!proxy_checkref(proxy))
566 return -1;
567 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
568}
569
570
571/* mapping slots */
572
Martin v. Löwis18e16552006-02-15 17:27:45 +0000573static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000574proxy_length(PyWeakReference *proxy)
575{
576 if (!proxy_checkref(proxy))
577 return -1;
578 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
579}
580
581WRAP_BINARY(proxy_getitem, PyObject_GetItem)
582
583static int
584proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
585{
586 if (!proxy_checkref(proxy))
587 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000588
589 if (value == NULL)
590 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
591 else
592 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000593}
594
Fred Drakef16c3dc2002-08-09 18:34:16 +0000595/* iterator slots */
596
597static PyObject *
598proxy_iter(PyWeakReference *proxy)
599{
600 if (!proxy_checkref(proxy))
601 return NULL;
602 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
603}
604
605static PyObject *
606proxy_iternext(PyWeakReference *proxy)
607{
608 if (!proxy_checkref(proxy))
609 return NULL;
610 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
611}
612
Fred Drake8844d522001-10-05 21:52:26 +0000613
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000614WRAP_METHOD(proxy_unicode, "__unicode__");
615
616
617static PyMethodDef proxy_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000618 {"__unicode__", (PyCFunction)proxy_unicode, METH_NOARGS},
619 {NULL, NULL}
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000620};
621
622
Fred Drake8844d522001-10-05 21:52:26 +0000623static PyNumberMethods proxy_as_number = {
Georg Brandl347b3002006-03-30 11:57:00 +0000624 proxy_add, /*nb_add*/
625 proxy_sub, /*nb_subtract*/
626 proxy_mul, /*nb_multiply*/
627 proxy_div, /*nb_divide*/
628 proxy_mod, /*nb_remainder*/
629 proxy_divmod, /*nb_divmod*/
630 proxy_pow, /*nb_power*/
631 proxy_neg, /*nb_negative*/
632 proxy_pos, /*nb_positive*/
633 proxy_abs, /*nb_absolute*/
634 (inquiry)proxy_nonzero, /*nb_nonzero*/
635 proxy_invert, /*nb_invert*/
636 proxy_lshift, /*nb_lshift*/
637 proxy_rshift, /*nb_rshift*/
638 proxy_and, /*nb_and*/
639 proxy_xor, /*nb_xor*/
640 proxy_or, /*nb_or*/
641 0, /*nb_coerce*/
642 proxy_int, /*nb_int*/
643 proxy_long, /*nb_long*/
644 proxy_float, /*nb_float*/
645 0, /*nb_oct*/
646 0, /*nb_hex*/
647 proxy_iadd, /*nb_inplace_add*/
648 proxy_isub, /*nb_inplace_subtract*/
649 proxy_imul, /*nb_inplace_multiply*/
650 proxy_idiv, /*nb_inplace_divide*/
651 proxy_imod, /*nb_inplace_remainder*/
652 proxy_ipow, /*nb_inplace_power*/
653 proxy_ilshift, /*nb_inplace_lshift*/
654 proxy_irshift, /*nb_inplace_rshift*/
655 proxy_iand, /*nb_inplace_and*/
656 proxy_ixor, /*nb_inplace_xor*/
657 proxy_ior, /*nb_inplace_or*/
Georg Brandl88659b02008-05-20 08:40:43 +0000658 proxy_floor_div, /*nb_floor_divide*/
659 proxy_true_div, /*nb_true_divide*/
660 proxy_ifloor_div, /*nb_inplace_floor_divide*/
661 proxy_itrue_div, /*nb_inplace_true_divide*/
662 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000663};
664
665static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000666 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000667 0, /*sq_concat*/
668 0, /*sq_repeat*/
669 0, /*sq_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000670 (ssizessizeargfunc)proxy_slice, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000671 0, /*sq_ass_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000672 (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000673 (objobjproc)proxy_contains, /* sq_contains */
674};
675
676static PyMappingMethods proxy_as_mapping = {
Georg Brandl347b3002006-03-30 11:57:00 +0000677 (lenfunc)proxy_length, /*mp_length*/
678 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000679 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
680};
681
682
683PyTypeObject
684_PyWeakref_ProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000685 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000686 "weakproxy",
687 sizeof(PyWeakReference),
688 0,
689 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000690 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000691 0, /* tp_print */
692 0, /* tp_getattr */
693 0, /* tp_setattr */
694 proxy_compare, /* tp_compare */
695 (reprfunc)proxy_repr, /* tp_repr */
696 &proxy_as_number, /* tp_as_number */
697 &proxy_as_sequence, /* tp_as_sequence */
698 &proxy_as_mapping, /* tp_as_mapping */
699 0, /* tp_hash */
700 0, /* tp_call */
Georg Brandl347b3002006-03-30 11:57:00 +0000701 proxy_str, /* tp_str */
702 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000703 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000704 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000705 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000706 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
707 0, /* tp_doc */
708 (traverseproc)gc_traverse, /* tp_traverse */
709 (inquiry)gc_clear, /* tp_clear */
710 0, /* tp_richcompare */
711 0, /* tp_weaklistoffset */
712 (getiterfunc)proxy_iter, /* tp_iter */
713 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000714 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000715};
716
717
718PyTypeObject
719_PyWeakref_CallableProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000720 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000721 "weakcallableproxy",
722 sizeof(PyWeakReference),
723 0,
724 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000725 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000726 0, /* tp_print */
727 0, /* tp_getattr */
728 0, /* tp_setattr */
729 proxy_compare, /* tp_compare */
730 (unaryfunc)proxy_repr, /* tp_repr */
731 &proxy_as_number, /* tp_as_number */
732 &proxy_as_sequence, /* tp_as_sequence */
733 &proxy_as_mapping, /* tp_as_mapping */
734 0, /* tp_hash */
735 proxy_call, /* tp_call */
736 proxy_str, /* tp_str */
Georg Brandl347b3002006-03-30 11:57:00 +0000737 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000738 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000739 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000740 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000741 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
742 0, /* tp_doc */
743 (traverseproc)gc_traverse, /* tp_traverse */
744 (inquiry)gc_clear, /* tp_clear */
745 0, /* tp_richcompare */
746 0, /* tp_weaklistoffset */
747 (getiterfunc)proxy_iter, /* tp_iter */
748 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000749};
750
751
Fred Drake8844d522001-10-05 21:52:26 +0000752
753PyObject *
754PyWeakref_NewRef(PyObject *ob, PyObject *callback)
755{
756 PyWeakReference *result = NULL;
757 PyWeakReference **list;
758 PyWeakReference *ref, *proxy;
759
Christian Heimese93237d2007-12-19 02:37:44 +0000760 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000761 PyErr_Format(PyExc_TypeError,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000762 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000763 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000764 return NULL;
765 }
766 list = GET_WEAKREFS_LISTPTR(ob);
767 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000768 if (callback == Py_None)
769 callback = NULL;
770 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000771 /* return existing weak reference if it exists */
772 result = ref;
773 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000774 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000775 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000776 /* Note: new_weakref() can trigger cyclic GC, so the weakref
777 list on ob can be mutated. This means that the ref and
778 proxy pointers we got back earlier may have been collected,
779 so we need to compute these values again before we use
780 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000781 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000782 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000783 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000784 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000785 if (ref == NULL)
786 insert_head(result, list);
787 else {
788 /* Someone else added a ref without a callback
789 during GC. Return that one instead of this one
790 to avoid violating the invariants of the list
791 of weakrefs for ob. */
792 Py_DECREF(result);
793 Py_INCREF(ref);
794 result = ref;
795 }
Fred Drake8844d522001-10-05 21:52:26 +0000796 }
797 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000798 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000799
Fred Drakebc875f52004-02-04 23:14:14 +0000800 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000801 if (prev == NULL)
802 insert_head(result, list);
803 else
804 insert_after(result, prev);
805 }
Fred Drake8844d522001-10-05 21:52:26 +0000806 }
807 }
808 return (PyObject *) result;
809}
810
811
812PyObject *
813PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
814{
815 PyWeakReference *result = NULL;
816 PyWeakReference **list;
817 PyWeakReference *ref, *proxy;
818
Christian Heimese93237d2007-12-19 02:37:44 +0000819 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000820 PyErr_Format(PyExc_TypeError,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000821 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000822 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000823 return NULL;
824 }
825 list = GET_WEAKREFS_LISTPTR(ob);
826 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000827 if (callback == Py_None)
828 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000829 if (callback == NULL)
830 /* attempt to return an existing weak reference if it exists */
831 result = proxy;
832 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000833 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000834 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000835 /* Note: new_weakref() can trigger cyclic GC, so the weakref
836 list on ob can be mutated. This means that the ref and
837 proxy pointers we got back earlier may have been collected,
838 so we need to compute these values again before we use
839 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000840 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000841 if (result != NULL) {
842 PyWeakReference *prev;
843
844 if (PyCallable_Check(ob))
Christian Heimese93237d2007-12-19 02:37:44 +0000845 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000846 else
Christian Heimese93237d2007-12-19 02:37:44 +0000847 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000848 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000849 if (callback == NULL) {
850 if (proxy != NULL) {
851 /* Someone else added a proxy without a callback
852 during GC. Return that one instead of this one
853 to avoid violating the invariants of the list
854 of weakrefs for ob. */
855 Py_DECREF(result);
856 Py_INCREF(result = proxy);
857 goto skip_insert;
858 }
Fred Drake8844d522001-10-05 21:52:26 +0000859 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000860 }
Fred Drake8844d522001-10-05 21:52:26 +0000861 else
862 prev = (proxy == NULL) ? ref : proxy;
863
864 if (prev == NULL)
865 insert_head(result, list);
866 else
867 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000868 skip_insert:
869 ;
Fred Drake8844d522001-10-05 21:52:26 +0000870 }
871 }
872 return (PyObject *) result;
873}
874
875
876PyObject *
877PyWeakref_GetObject(PyObject *ref)
878{
879 if (ref == NULL || !PyWeakref_Check(ref)) {
880 PyErr_BadInternalCall();
881 return NULL;
882 }
883 return PyWeakref_GET_OBJECT(ref);
884}
885
Tim Petersead8b7a2004-10-30 23:09:22 +0000886/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
887 * handle_weakrefs().
888 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000889static void
890handle_callback(PyWeakReference *ref, PyObject *callback)
891{
Georg Brandl684fd0c2006-05-25 19:15:31 +0000892 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000893
894 if (cbresult == NULL)
895 PyErr_WriteUnraisable(callback);
896 else
897 Py_DECREF(cbresult);
898}
899
900/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000901 *
902 * This iterates through the weak references for 'object' and calls callbacks
903 * for those references which have one. It returns when all callbacks have
904 * been attempted.
905 */
906void
907PyObject_ClearWeakRefs(PyObject *object)
908{
909 PyWeakReference **list;
910
911 if (object == NULL
Christian Heimese93237d2007-12-19 02:37:44 +0000912 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000913 || object->ob_refcnt != 0) {
914 PyErr_BadInternalCall();
915 return;
916 }
917 list = GET_WEAKREFS_LISTPTR(object);
918 /* Remove the callback-less basic and proxy references */
919 if (*list != NULL && (*list)->wr_callback == NULL) {
920 clear_weakref(*list);
921 if (*list != NULL && (*list)->wr_callback == NULL)
922 clear_weakref(*list);
923 }
924 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000925 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000926 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000927 int restore_error = PyErr_Occurred() ? 1 : 0;
928 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000929
Fred Drakeef8ebd12001-12-10 23:44:54 +0000930 if (restore_error)
931 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000932 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000933 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000934
Fred Drakeef8ebd12001-12-10 23:44:54 +0000935 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000936 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000937 if (callback != NULL) {
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000938 if (current->ob_refcnt > 0)
939 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000940 Py_DECREF(callback);
941 }
Fred Drake8844d522001-10-05 21:52:26 +0000942 }
943 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000944 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000945 Py_ssize_t i = 0;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000946
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000947 tuple = PyTuple_New(count * 2);
948 if (tuple == NULL) {
949 if (restore_error)
950 PyErr_Fetch(&err_type, &err_value, &err_tb);
951 return;
952 }
Fred Drake8844d522001-10-05 21:52:26 +0000953
954 for (i = 0; i < count; ++i) {
955 PyWeakReference *next = current->wr_next;
956
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000957 if (current->ob_refcnt > 0)
958 {
959 Py_INCREF(current);
960 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
961 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
962 }
963 else {
964 Py_DECREF(current->wr_callback);
965 }
Fred Drake8844d522001-10-05 21:52:26 +0000966 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000967 clear_weakref(current);
968 current = next;
969 }
970 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000971 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000972
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000973 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000974 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000975 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
976 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000977 }
Fred Drake8844d522001-10-05 21:52:26 +0000978 }
979 Py_DECREF(tuple);
980 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000981 if (restore_error)
982 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000983 }
984}