blob: b49dcee1adea156e47a32fd08bd50340a3c371c1 [file] [log] [blame]
Fred Drake8844d522001-10-05 21:52:26 +00001#include "Python.h"
2#include "structmember.h"
3
4
5#define GET_WEAKREFS_LISTPTR(o) \
6 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
7
Fred Drake8844d522001-10-05 21:52:26 +00008
Thomas Wouters0e3f5912006-08-11 14:57:12 +00009Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +000010_PyWeakref_GetWeakrefCount(PyWeakReference *head)
11{
Thomas Wouters0e3f5912006-08-11 14:57:12 +000012 Py_ssize_t count = 0;
Fred Drake8844d522001-10-05 21:52:26 +000013
14 while (head != NULL) {
15 ++count;
16 head = head->wr_next;
17 }
18 return count;
19}
20
21
Fred Drake0a4dd392004-07-02 18:57:45 +000022static void
23init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
24{
25 self->hash = -1;
26 self->wr_object = ob;
27 Py_XINCREF(callback);
28 self->wr_callback = callback;
29}
30
Fred Drake8844d522001-10-05 21:52:26 +000031static PyWeakReference *
Neil Schemenauer38a89162002-03-27 15:18:21 +000032new_weakref(PyObject *ob, PyObject *callback)
Fred Drake8844d522001-10-05 21:52:26 +000033{
34 PyWeakReference *result;
35
Neil Schemenauer38a89162002-03-27 15:18:21 +000036 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
37 if (result) {
Fred Drake0a4dd392004-07-02 18:57:45 +000038 init_weakref(result, ob, callback);
Neil Schemenauer38a89162002-03-27 15:18:21 +000039 PyObject_GC_Track(result);
40 }
Fred Drake8844d522001-10-05 21:52:26 +000041 return result;
42}
43
44
45/* This function clears the passed-in reference and removes it from the
46 * list of weak references for the referent. This is the only code that
47 * removes an item from the doubly-linked list of weak references for an
48 * object; it is also responsible for clearing the callback slot.
49 */
50static void
51clear_weakref(PyWeakReference *self)
52{
53 PyObject *callback = self->wr_callback;
54
Antoine Pitrou62a0d6e2012-12-08 21:15:26 +010055 if (self->wr_object != Py_None) {
56 PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
Fred Drake8844d522001-10-05 21:52:26 +000057
58 if (*list == self)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000059 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
60 then the weakref list itself (and thus the value of *list) will
61 end up being set to NULL. */
Fred Drake8844d522001-10-05 21:52:26 +000062 *list = self->wr_next;
63 self->wr_object = Py_None;
Fred Drake8844d522001-10-05 21:52:26 +000064 if (self->wr_prev != NULL)
65 self->wr_prev->wr_next = self->wr_next;
66 if (self->wr_next != NULL)
67 self->wr_next->wr_prev = self->wr_prev;
68 self->wr_prev = NULL;
69 self->wr_next = NULL;
Tim Peters403a2032003-11-20 21:21:46 +000070 }
71 if (callback != NULL) {
72 Py_DECREF(callback);
73 self->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +000074 }
75}
76
Tim Peters403a2032003-11-20 21:21:46 +000077/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
78 * the callback intact and uncalled. It must be possible to call self's
79 * tp_dealloc() after calling this, so self has to be left in a sane enough
80 * state for that to work. We expect tp_dealloc to decref the callback
81 * then. The reason for not letting clear_weakref() decref the callback
82 * right now is that if the callback goes away, that may in turn trigger
83 * another callback (if a weak reference to the callback exists) -- running
84 * arbitrary Python code in the middle of gc is a disaster. The convolution
85 * here allows gc to delay triggering such callbacks until the world is in
86 * a sane state again.
87 */
88void
89_PyWeakref_ClearRef(PyWeakReference *self)
90{
91 PyObject *callback;
92
93 assert(self != NULL);
94 assert(PyWeakref_Check(self));
95 /* Preserve and restore the callback around clear_weakref. */
96 callback = self->wr_callback;
97 self->wr_callback = NULL;
98 clear_weakref(self);
99 self->wr_callback = callback;
100}
Fred Drake8844d522001-10-05 21:52:26 +0000101
102static void
Fred Drake0a4dd392004-07-02 18:57:45 +0000103weakref_dealloc(PyObject *self)
Fred Drake8844d522001-10-05 21:52:26 +0000104{
Fred Drake0a4dd392004-07-02 18:57:45 +0000105 PyObject_GC_UnTrack(self);
106 clear_weakref((PyWeakReference *) self);
Christian Heimes90aa7642007-12-19 02:45:37 +0000107 Py_TYPE(self)->tp_free(self);
Fred Drake8844d522001-10-05 21:52:26 +0000108}
109
110
111static int
112gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
113{
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000114 Py_VISIT(self->wr_callback);
Fred Drake8844d522001-10-05 21:52:26 +0000115 return 0;
116}
117
118
119static int
120gc_clear(PyWeakReference *self)
121{
122 clear_weakref(self);
123 return 0;
124}
125
126
127static PyObject *
128weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
129{
Martin v. Löwis15e62742006-02-27 16:46:16 +0000130 static char *kwlist[] = {NULL};
Fred Drake8844d522001-10-05 21:52:26 +0000131
Martin v. Löwis15e62742006-02-27 16:46:16 +0000132 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
Fred Drake8844d522001-10-05 21:52:26 +0000133 PyObject *object = PyWeakref_GET_OBJECT(self);
134 Py_INCREF(object);
135 return (object);
136 }
137 return NULL;
138}
139
140
Benjamin Peterson8f67d082010-10-17 20:54:53 +0000141static Py_hash_t
Fred Drake8844d522001-10-05 21:52:26 +0000142weakref_hash(PyWeakReference *self)
143{
144 if (self->hash != -1)
145 return self->hash;
146 if (PyWeakref_GET_OBJECT(self) == Py_None) {
147 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
148 return -1;
149 }
150 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
151 return self->hash;
152}
Tim Peters403a2032003-11-20 21:21:46 +0000153
Fred Drake8844d522001-10-05 21:52:26 +0000154
155static PyObject *
156weakref_repr(PyWeakReference *self)
157{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100158 PyObject *name, *repr;
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200159 _Py_IDENTIFIER(__name__);
Victor Stinner499dfcf2011-03-21 13:26:24 +0100160
161 if (PyWeakref_GET_OBJECT(self) == Py_None)
162 return PyUnicode_FromFormat("<weakref at %p; dead>", self);
163
Martin v. Löwis1ee1b6f2011-10-10 18:11:30 +0200164 name = _PyObject_GetAttrId(PyWeakref_GET_OBJECT(self), &PyId___name__);
Victor Stinner499dfcf2011-03-21 13:26:24 +0100165 if (name == NULL || !PyUnicode_Check(name)) {
166 if (name == NULL)
167 PyErr_Clear();
168 repr = PyUnicode_FromFormat(
169 "<weakref at %p; to '%s' at %p>",
170 self,
171 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
172 PyWeakref_GET_OBJECT(self));
Fred Drake8844d522001-10-05 21:52:26 +0000173 }
174 else {
Victor Stinner499dfcf2011-03-21 13:26:24 +0100175 repr = PyUnicode_FromFormat(
176 "<weakref at %p; to '%s' at %p (%U)>",
177 self,
178 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
179 PyWeakref_GET_OBJECT(self),
180 name);
Fred Drake8844d522001-10-05 21:52:26 +0000181 }
Victor Stinner499dfcf2011-03-21 13:26:24 +0100182 Py_XDECREF(name);
183 return repr;
Fred Drake8844d522001-10-05 21:52:26 +0000184}
185
186/* Weak references only support equality, not ordering. Two weak references
187 are equal if the underlying objects are equal. If the underlying object has
188 gone away, they are equal if they are identical. */
189
190static PyObject *
191weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
192{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000193 if ((op != Py_EQ && op != Py_NE) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000194 !PyWeakref_Check(self) ||
195 !PyWeakref_Check(other)) {
Brian Curtindfc80e32011-08-10 20:28:54 -0500196 Py_RETURN_NOTIMPLEMENTED;
Fred Drake8844d522001-10-05 21:52:26 +0000197 }
198 if (PyWeakref_GET_OBJECT(self) == Py_None
199 || PyWeakref_GET_OBJECT(other) == Py_None) {
Antoine Pitroue11fecb2012-11-11 19:36:51 +0100200 int res = (self == other);
201 if (op == Py_NE)
202 res = !res;
203 if (res)
204 Py_RETURN_TRUE;
205 else
206 Py_RETURN_FALSE;
Fred Drake8844d522001-10-05 21:52:26 +0000207 }
208 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
209 PyWeakref_GET_OBJECT(other), op);
210}
211
Fred Drake0a4dd392004-07-02 18:57:45 +0000212/* Given the head of an object's list of weak references, extract the
213 * two callback-less refs (ref and proxy). Used to determine if the
214 * shared references exist and to determine the back link for newly
215 * inserted references.
216 */
217static void
218get_basic_refs(PyWeakReference *head,
219 PyWeakReference **refp, PyWeakReference **proxyp)
220{
221 *refp = NULL;
222 *proxyp = NULL;
223
224 if (head != NULL && head->wr_callback == NULL) {
225 /* We need to be careful that the "basic refs" aren't
226 subclasses of the main types. That complicates this a
227 little. */
228 if (PyWeakref_CheckRefExact(head)) {
229 *refp = head;
230 head = head->wr_next;
231 }
232 if (head != NULL
233 && head->wr_callback == NULL
234 && PyWeakref_CheckProxy(head)) {
235 *proxyp = head;
236 /* head = head->wr_next; */
237 }
238 }
239}
240
241/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
242static void
243insert_after(PyWeakReference *newref, PyWeakReference *prev)
244{
245 newref->wr_prev = prev;
246 newref->wr_next = prev->wr_next;
247 if (prev->wr_next != NULL)
248 prev->wr_next->wr_prev = newref;
249 prev->wr_next = newref;
250}
251
252/* Insert 'newref' at the head of the list; 'list' points to the variable
253 * that stores the head.
254 */
255static void
256insert_head(PyWeakReference *newref, PyWeakReference **list)
257{
258 PyWeakReference *next = *list;
259
260 newref->wr_prev = NULL;
261 newref->wr_next = next;
262 if (next != NULL)
263 next->wr_prev = newref;
264 *list = newref;
265}
266
267static int
268parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
269 PyObject **obp, PyObject **callbackp)
270{
271 /* XXX Should check that kwargs == NULL or is empty. */
272 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
273}
274
275static PyObject *
276weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
277{
278 PyWeakReference *self = NULL;
279 PyObject *ob, *callback = NULL;
280
281 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
282 PyWeakReference *ref, *proxy;
283 PyWeakReference **list;
284
Christian Heimes90aa7642007-12-19 02:45:37 +0000285 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000286 PyErr_Format(PyExc_TypeError,
287 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000288 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000289 return NULL;
290 }
291 if (callback == Py_None)
292 callback = NULL;
293 list = GET_WEAKREFS_LISTPTR(ob);
294 get_basic_refs(*list, &ref, &proxy);
295 if (callback == NULL && type == &_PyWeakref_RefType) {
296 if (ref != NULL) {
297 /* We can re-use an existing reference. */
298 Py_INCREF(ref);
299 return (PyObject *)ref;
300 }
301 }
302 /* We have to create a new reference. */
303 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
304 list on ob can be mutated. This means that the ref and
305 proxy pointers we got back earlier may have been collected,
306 so we need to compute these values again before we use
307 them. */
308 self = (PyWeakReference *) (type->tp_alloc(type, 0));
309 if (self != NULL) {
310 init_weakref(self, ob, callback);
311 if (callback == NULL && type == &_PyWeakref_RefType) {
312 insert_head(self, list);
313 }
314 else {
315 PyWeakReference *prev;
316
317 get_basic_refs(*list, &ref, &proxy);
318 prev = (proxy == NULL) ? ref : proxy;
319 if (prev == NULL)
320 insert_head(self, list);
321 else
322 insert_after(self, prev);
323 }
324 }
325 }
326 return (PyObject *)self;
327}
328
329static int
330weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
331{
332 PyObject *tmp;
333
334 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
335 return 0;
336 else
Benjamin Peterson9aa42992008-09-10 21:57:34 +0000337 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000338}
339
Fred Drake8844d522001-10-05 21:52:26 +0000340
341PyTypeObject
342_PyWeakref_RefType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000343 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000344 "weakref",
345 sizeof(PyWeakReference),
346 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000347 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000348 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000349 0, /*tp_getattr*/
350 0, /*tp_setattr*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000351 0, /*tp_reserved*/
Fred Drake8844d522001-10-05 21:52:26 +0000352 (reprfunc)weakref_repr, /*tp_repr*/
353 0, /*tp_as_number*/
354 0, /*tp_as_sequence*/
355 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000356 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000357 (ternaryfunc)weakref_call, /*tp_call*/
358 0, /*tp_str*/
359 0, /*tp_getattro*/
360 0, /*tp_setattro*/
361 0, /*tp_as_buffer*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000362 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000363 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000364 0, /*tp_doc*/
365 (traverseproc)gc_traverse, /*tp_traverse*/
366 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000367 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000368 0, /*tp_weaklistoffset*/
369 0, /*tp_iter*/
370 0, /*tp_iternext*/
371 0, /*tp_methods*/
372 0, /*tp_members*/
373 0, /*tp_getset*/
374 0, /*tp_base*/
375 0, /*tp_dict*/
376 0, /*tp_descr_get*/
377 0, /*tp_descr_set*/
378 0, /*tp_dictoffset*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000379 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000380 PyType_GenericAlloc, /*tp_alloc*/
381 weakref___new__, /*tp_new*/
382 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000383};
384
385
386static int
387proxy_checkref(PyWeakReference *proxy)
388{
389 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
390 PyErr_SetString(PyExc_ReferenceError,
391 "weakly-referenced object no longer exists");
392 return 0;
393 }
394 return 1;
395}
396
397
Fred Drake73006d02001-10-18 18:04:18 +0000398/* If a parameter is a proxy, check that it is still "live" and wrap it,
399 * replacing the original value with the raw object. Raises ReferenceError
400 * if the param is a dead proxy.
401 */
402#define UNWRAP(o) \
403 if (PyWeakref_CheckProxy(o)) { \
404 if (!proxy_checkref((PyWeakReference *)o)) \
405 return NULL; \
406 o = PyWeakref_GET_OBJECT(o); \
407 }
408
Fred Drake2a908f62001-12-19 16:44:30 +0000409#define UNWRAP_I(o) \
410 if (PyWeakref_CheckProxy(o)) { \
411 if (!proxy_checkref((PyWeakReference *)o)) \
412 return -1; \
413 o = PyWeakref_GET_OBJECT(o); \
414 }
415
Fred Drake8844d522001-10-05 21:52:26 +0000416#define WRAP_UNARY(method, generic) \
417 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000418 method(PyObject *proxy) { \
419 UNWRAP(proxy); \
420 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000421 }
422
423#define WRAP_BINARY(method, generic) \
424 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000425 method(PyObject *x, PyObject *y) { \
426 UNWRAP(x); \
427 UNWRAP(y); \
428 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000429 }
430
Fred Drake31f4d1f2001-10-18 19:21:46 +0000431/* Note that the third arg needs to be checked for NULL since the tp_call
432 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000433 */
Fred Drake8844d522001-10-05 21:52:26 +0000434#define WRAP_TERNARY(method, generic) \
435 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000436 method(PyObject *proxy, PyObject *v, PyObject *w) { \
437 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000438 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000439 if (w != NULL) \
440 UNWRAP(w); \
441 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000442 }
443
Benjamin Peterson32019772009-11-19 03:08:32 +0000444#define WRAP_METHOD(method, special) \
445 static PyObject * \
446 method(PyObject *proxy) { \
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200447 _Py_IDENTIFIER(special); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448 UNWRAP(proxy); \
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200449 return _PyObject_CallMethodId(proxy, &PyId_##special, ""); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000450 }
Benjamin Peterson32019772009-11-19 03:08:32 +0000451
Fred Drake8844d522001-10-05 21:52:26 +0000452
453/* direct slots */
454
455WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
456WRAP_UNARY(proxy_str, PyObject_Str)
457WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
458
Fred Drake8844d522001-10-05 21:52:26 +0000459static PyObject *
460proxy_repr(PyWeakReference *proxy)
461{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100462 return PyUnicode_FromFormat(
463 "<weakproxy at %p to %s at %p>",
464 proxy,
465 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
466 PyWeakref_GET_OBJECT(proxy));
Fred Drake8844d522001-10-05 21:52:26 +0000467}
468
469
470static int
471proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
472{
473 if (!proxy_checkref(proxy))
474 return -1;
475 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
476}
477
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000478static PyObject *
479proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000480{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000481 UNWRAP(proxy);
482 UNWRAP(v);
483 return PyObject_RichCompare(proxy, v, op);
Fred Drake8844d522001-10-05 21:52:26 +0000484}
485
486/* number slots */
487WRAP_BINARY(proxy_add, PyNumber_Add)
488WRAP_BINARY(proxy_sub, PyNumber_Subtract)
489WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000490WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
491WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000492WRAP_BINARY(proxy_mod, PyNumber_Remainder)
493WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
494WRAP_TERNARY(proxy_pow, PyNumber_Power)
495WRAP_UNARY(proxy_neg, PyNumber_Negative)
496WRAP_UNARY(proxy_pos, PyNumber_Positive)
497WRAP_UNARY(proxy_abs, PyNumber_Absolute)
498WRAP_UNARY(proxy_invert, PyNumber_Invert)
499WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
500WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
501WRAP_BINARY(proxy_and, PyNumber_And)
502WRAP_BINARY(proxy_xor, PyNumber_Xor)
503WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000504WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000505WRAP_UNARY(proxy_float, PyNumber_Float)
506WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
507WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
508WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000509WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
510WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000511WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
512WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
513WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
514WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
515WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
516WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
517WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000518WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000519
Tim Peters403a2032003-11-20 21:21:46 +0000520static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000521proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000522{
523 PyObject *o = PyWeakref_GET_OBJECT(proxy);
524 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000525 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000526 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000527}
528
Fred Drake0a4dd392004-07-02 18:57:45 +0000529static void
530proxy_dealloc(PyWeakReference *self)
531{
532 if (self->wr_callback != NULL)
533 PyObject_GC_UnTrack((PyObject *)self);
534 clear_weakref(self);
535 PyObject_GC_Del(self);
536}
537
Fred Drake8844d522001-10-05 21:52:26 +0000538/* sequence slots */
539
Fred Drake8844d522001-10-05 21:52:26 +0000540static int
541proxy_contains(PyWeakReference *proxy, PyObject *value)
542{
543 if (!proxy_checkref(proxy))
544 return -1;
545 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
546}
547
548
549/* mapping slots */
550
Martin v. Löwis18e16552006-02-15 17:27:45 +0000551static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000552proxy_length(PyWeakReference *proxy)
553{
554 if (!proxy_checkref(proxy))
555 return -1;
556 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
557}
558
559WRAP_BINARY(proxy_getitem, PyObject_GetItem)
560
561static int
562proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
563{
564 if (!proxy_checkref(proxy))
565 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000566
567 if (value == NULL)
568 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
569 else
570 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000571}
572
Fred Drakef16c3dc2002-08-09 18:34:16 +0000573/* iterator slots */
574
575static PyObject *
576proxy_iter(PyWeakReference *proxy)
577{
578 if (!proxy_checkref(proxy))
579 return NULL;
580 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
581}
582
583static PyObject *
584proxy_iternext(PyWeakReference *proxy)
585{
586 if (!proxy_checkref(proxy))
587 return NULL;
588 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
589}
590
Fred Drake8844d522001-10-05 21:52:26 +0000591
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200592WRAP_METHOD(proxy_bytes, __bytes__)
Benjamin Peterson32019772009-11-19 03:08:32 +0000593
594
595static PyMethodDef proxy_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000596 {"__bytes__", (PyCFunction)proxy_bytes, METH_NOARGS},
597 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000598};
599
600
Fred Drake8844d522001-10-05 21:52:26 +0000601static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000602 proxy_add, /*nb_add*/
603 proxy_sub, /*nb_subtract*/
604 proxy_mul, /*nb_multiply*/
605 proxy_mod, /*nb_remainder*/
606 proxy_divmod, /*nb_divmod*/
607 proxy_pow, /*nb_power*/
608 proxy_neg, /*nb_negative*/
609 proxy_pos, /*nb_positive*/
610 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000611 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000612 proxy_invert, /*nb_invert*/
613 proxy_lshift, /*nb_lshift*/
614 proxy_rshift, /*nb_rshift*/
615 proxy_and, /*nb_and*/
616 proxy_xor, /*nb_xor*/
617 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000618 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000619 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000620 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000621 proxy_iadd, /*nb_inplace_add*/
622 proxy_isub, /*nb_inplace_subtract*/
623 proxy_imul, /*nb_inplace_multiply*/
624 proxy_imod, /*nb_inplace_remainder*/
625 proxy_ipow, /*nb_inplace_power*/
626 proxy_ilshift, /*nb_inplace_lshift*/
627 proxy_irshift, /*nb_inplace_rshift*/
628 proxy_iand, /*nb_inplace_and*/
629 proxy_ixor, /*nb_inplace_xor*/
630 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000631 proxy_floor_div, /*nb_floor_divide*/
632 proxy_true_div, /*nb_true_divide*/
633 proxy_ifloor_div, /*nb_inplace_floor_divide*/
634 proxy_itrue_div, /*nb_inplace_true_divide*/
635 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000636};
637
638static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000639 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000640 0, /*sq_concat*/
641 0, /*sq_repeat*/
642 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000643 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000644 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000646 (objobjproc)proxy_contains, /* sq_contains */
647};
648
649static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000650 (lenfunc)proxy_length, /*mp_length*/
651 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000652 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
653};
654
655
656PyTypeObject
657_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000658 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000659 "weakproxy",
660 sizeof(PyWeakReference),
661 0,
662 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000663 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 0, /* tp_print */
665 0, /* tp_getattr */
666 0, /* tp_setattr */
667 0, /* tp_reserved */
668 (reprfunc)proxy_repr, /* tp_repr */
669 &proxy_as_number, /* tp_as_number */
670 &proxy_as_sequence, /* tp_as_sequence */
671 &proxy_as_mapping, /* tp_as_mapping */
672 0, /* tp_hash */
673 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000674 proxy_str, /* tp_str */
675 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000676 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000678 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000679 0, /* tp_doc */
680 (traverseproc)gc_traverse, /* tp_traverse */
681 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000682 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000683 0, /* tp_weaklistoffset */
684 (getiterfunc)proxy_iter, /* tp_iter */
685 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000686 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000687};
688
689
690PyTypeObject
691_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000692 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000693 "weakcallableproxy",
694 sizeof(PyWeakReference),
695 0,
696 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000697 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000698 0, /* tp_print */
699 0, /* tp_getattr */
700 0, /* tp_setattr */
701 0, /* tp_reserved */
702 (unaryfunc)proxy_repr, /* tp_repr */
703 &proxy_as_number, /* tp_as_number */
704 &proxy_as_sequence, /* tp_as_sequence */
705 &proxy_as_mapping, /* tp_as_mapping */
706 0, /* tp_hash */
707 proxy_call, /* tp_call */
708 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000709 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000710 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000711 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000712 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000713 0, /* tp_doc */
714 (traverseproc)gc_traverse, /* tp_traverse */
715 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000716 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000717 0, /* tp_weaklistoffset */
718 (getiterfunc)proxy_iter, /* tp_iter */
719 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000720};
721
722
Fred Drake8844d522001-10-05 21:52:26 +0000723
724PyObject *
725PyWeakref_NewRef(PyObject *ob, PyObject *callback)
726{
727 PyWeakReference *result = NULL;
728 PyWeakReference **list;
729 PyWeakReference *ref, *proxy;
730
Christian Heimes90aa7642007-12-19 02:45:37 +0000731 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000732 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000733 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000734 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000735 return NULL;
736 }
737 list = GET_WEAKREFS_LISTPTR(ob);
738 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000739 if (callback == Py_None)
740 callback = NULL;
741 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000742 /* return existing weak reference if it exists */
743 result = ref;
744 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000745 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000746 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000747 /* Note: new_weakref() can trigger cyclic GC, so the weakref
748 list on ob can be mutated. This means that the ref and
749 proxy pointers we got back earlier may have been collected,
750 so we need to compute these values again before we use
751 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000752 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000753 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000754 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000755 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000756 if (ref == NULL)
757 insert_head(result, list);
758 else {
759 /* Someone else added a ref without a callback
760 during GC. Return that one instead of this one
761 to avoid violating the invariants of the list
762 of weakrefs for ob. */
763 Py_DECREF(result);
764 Py_INCREF(ref);
765 result = ref;
766 }
Fred Drake8844d522001-10-05 21:52:26 +0000767 }
768 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000769 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000770
Fred Drakebc875f52004-02-04 23:14:14 +0000771 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000772 if (prev == NULL)
773 insert_head(result, list);
774 else
775 insert_after(result, prev);
776 }
Fred Drake8844d522001-10-05 21:52:26 +0000777 }
778 }
779 return (PyObject *) result;
780}
781
782
783PyObject *
784PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
785{
786 PyWeakReference *result = NULL;
787 PyWeakReference **list;
788 PyWeakReference *ref, *proxy;
789
Christian Heimes90aa7642007-12-19 02:45:37 +0000790 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000791 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000793 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000794 return NULL;
795 }
796 list = GET_WEAKREFS_LISTPTR(ob);
797 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000798 if (callback == Py_None)
799 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000800 if (callback == NULL)
801 /* attempt to return an existing weak reference if it exists */
802 result = proxy;
803 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000804 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000805 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000806 /* Note: new_weakref() can trigger cyclic GC, so the weakref
807 list on ob can be mutated. This means that the ref and
808 proxy pointers we got back earlier may have been collected,
809 so we need to compute these values again before we use
810 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000811 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000812 if (result != NULL) {
813 PyWeakReference *prev;
814
815 if (PyCallable_Check(ob))
Christian Heimes90aa7642007-12-19 02:45:37 +0000816 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000817 else
Christian Heimes90aa7642007-12-19 02:45:37 +0000818 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000819 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000820 if (callback == NULL) {
821 if (proxy != NULL) {
822 /* Someone else added a proxy without a callback
823 during GC. Return that one instead of this one
824 to avoid violating the invariants of the list
825 of weakrefs for ob. */
826 Py_DECREF(result);
827 Py_INCREF(result = proxy);
828 goto skip_insert;
829 }
Fred Drake8844d522001-10-05 21:52:26 +0000830 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000831 }
Fred Drake8844d522001-10-05 21:52:26 +0000832 else
833 prev = (proxy == NULL) ? ref : proxy;
834
835 if (prev == NULL)
836 insert_head(result, list);
837 else
838 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000839 skip_insert:
840 ;
Fred Drake8844d522001-10-05 21:52:26 +0000841 }
842 }
843 return (PyObject *) result;
844}
845
846
847PyObject *
848PyWeakref_GetObject(PyObject *ref)
849{
850 if (ref == NULL || !PyWeakref_Check(ref)) {
851 PyErr_BadInternalCall();
852 return NULL;
853 }
854 return PyWeakref_GET_OBJECT(ref);
855}
856
Tim Petersead8b7a2004-10-30 23:09:22 +0000857/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
858 * handle_weakrefs().
859 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000860static void
861handle_callback(PyWeakReference *ref, PyObject *callback)
862{
Thomas Wouters477c8d52006-05-27 19:21:47 +0000863 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000864
865 if (cbresult == NULL)
866 PyErr_WriteUnraisable(callback);
867 else
868 Py_DECREF(cbresult);
869}
870
871/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000872 *
873 * This iterates through the weak references for 'object' and calls callbacks
874 * for those references which have one. It returns when all callbacks have
875 * been attempted.
876 */
877void
878PyObject_ClearWeakRefs(PyObject *object)
879{
880 PyWeakReference **list;
881
882 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000883 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000884 || object->ob_refcnt != 0) {
885 PyErr_BadInternalCall();
886 return;
887 }
888 list = GET_WEAKREFS_LISTPTR(object);
889 /* Remove the callback-less basic and proxy references */
890 if (*list != NULL && (*list)->wr_callback == NULL) {
891 clear_weakref(*list);
892 if (*list != NULL && (*list)->wr_callback == NULL)
893 clear_weakref(*list);
894 }
895 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000896 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000897 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000898 int restore_error = PyErr_Occurred() ? 1 : 0;
899 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000900
Fred Drakeef8ebd12001-12-10 23:44:54 +0000901 if (restore_error)
902 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000903 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000904 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000905
Fred Drakeef8ebd12001-12-10 23:44:54 +0000906 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000907 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000908 if (callback != NULL) {
Benjamin Petersona38d1562008-06-16 20:47:12 +0000909 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000910 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000911 Py_DECREF(callback);
912 }
Fred Drake8844d522001-10-05 21:52:26 +0000913 }
914 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000915 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000916 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000917
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000918 tuple = PyTuple_New(count * 2);
919 if (tuple == NULL) {
920 if (restore_error)
921 PyErr_Fetch(&err_type, &err_value, &err_tb);
922 return;
923 }
Fred Drake8844d522001-10-05 21:52:26 +0000924
925 for (i = 0; i < count; ++i) {
926 PyWeakReference *next = current->wr_next;
927
Benjamin Petersona38d1562008-06-16 20:47:12 +0000928 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000929 {
930 Py_INCREF(current);
931 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
932 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
933 }
934 else {
935 Py_DECREF(current->wr_callback);
936 }
Fred Drake8844d522001-10-05 21:52:26 +0000937 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000938 clear_weakref(current);
939 current = next;
940 }
941 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000942 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000943
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000944 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000945 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000946 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
947 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000948 }
Fred Drake8844d522001-10-05 21:52:26 +0000949 }
950 Py_DECREF(tuple);
951 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000952 if (restore_error)
953 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000954 }
955}