blob: 7e6f36458bc693cffeee1e329196e0af0da9e52d [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{
Fred Drake0a4dd392004-07-02 18:57:45 +0000271 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
272}
273
274static PyObject *
275weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
276{
277 PyWeakReference *self = NULL;
278 PyObject *ob, *callback = NULL;
279
280 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
281 PyWeakReference *ref, *proxy;
282 PyWeakReference **list;
283
Christian Heimes90aa7642007-12-19 02:45:37 +0000284 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000285 PyErr_Format(PyExc_TypeError,
286 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000287 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000288 return NULL;
289 }
290 if (callback == Py_None)
291 callback = NULL;
292 list = GET_WEAKREFS_LISTPTR(ob);
293 get_basic_refs(*list, &ref, &proxy);
294 if (callback == NULL && type == &_PyWeakref_RefType) {
295 if (ref != NULL) {
296 /* We can re-use an existing reference. */
297 Py_INCREF(ref);
298 return (PyObject *)ref;
299 }
300 }
301 /* We have to create a new reference. */
302 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
303 list on ob can be mutated. This means that the ref and
304 proxy pointers we got back earlier may have been collected,
305 so we need to compute these values again before we use
306 them. */
307 self = (PyWeakReference *) (type->tp_alloc(type, 0));
308 if (self != NULL) {
309 init_weakref(self, ob, callback);
310 if (callback == NULL && type == &_PyWeakref_RefType) {
311 insert_head(self, list);
312 }
313 else {
314 PyWeakReference *prev;
315
316 get_basic_refs(*list, &ref, &proxy);
317 prev = (proxy == NULL) ? ref : proxy;
318 if (prev == NULL)
319 insert_head(self, list);
320 else
321 insert_after(self, prev);
322 }
323 }
324 }
325 return (PyObject *)self;
326}
327
328static int
329weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
330{
331 PyObject *tmp;
332
Serhiy Storchaka21eb4872016-05-07 15:41:09 +0300333 if (!_PyArg_NoKeywords("ref()", kwargs))
334 return -1;
335
Fred Drake0a4dd392004-07-02 18:57:45 +0000336 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
337 return 0;
338 else
Benjamin Peterson9aa42992008-09-10 21:57:34 +0000339 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000340}
341
Fred Drake8844d522001-10-05 21:52:26 +0000342
Mark Dickinson556e94b2013-04-13 15:45:44 +0100343static PyMemberDef weakref_members[] = {
344 {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY},
345 {NULL} /* Sentinel */
346};
347
Fred Drake8844d522001-10-05 21:52:26 +0000348PyTypeObject
349_PyWeakref_RefType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000350 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000351 "weakref",
352 sizeof(PyWeakReference),
353 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000354 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000355 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000356 0, /*tp_getattr*/
357 0, /*tp_setattr*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000358 0, /*tp_reserved*/
Fred Drake8844d522001-10-05 21:52:26 +0000359 (reprfunc)weakref_repr, /*tp_repr*/
360 0, /*tp_as_number*/
361 0, /*tp_as_sequence*/
362 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000363 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000364 (ternaryfunc)weakref_call, /*tp_call*/
365 0, /*tp_str*/
366 0, /*tp_getattro*/
367 0, /*tp_setattro*/
368 0, /*tp_as_buffer*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000369 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000370 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000371 0, /*tp_doc*/
372 (traverseproc)gc_traverse, /*tp_traverse*/
373 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000374 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000375 0, /*tp_weaklistoffset*/
376 0, /*tp_iter*/
377 0, /*tp_iternext*/
378 0, /*tp_methods*/
Mark Dickinson556e94b2013-04-13 15:45:44 +0100379 weakref_members, /*tp_members*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000380 0, /*tp_getset*/
381 0, /*tp_base*/
382 0, /*tp_dict*/
383 0, /*tp_descr_get*/
384 0, /*tp_descr_set*/
385 0, /*tp_dictoffset*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000386 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000387 PyType_GenericAlloc, /*tp_alloc*/
388 weakref___new__, /*tp_new*/
389 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000390};
391
392
393static int
394proxy_checkref(PyWeakReference *proxy)
395{
396 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
397 PyErr_SetString(PyExc_ReferenceError,
398 "weakly-referenced object no longer exists");
399 return 0;
400 }
401 return 1;
402}
403
404
Fred Drake73006d02001-10-18 18:04:18 +0000405/* If a parameter is a proxy, check that it is still "live" and wrap it,
406 * replacing the original value with the raw object. Raises ReferenceError
407 * if the param is a dead proxy.
408 */
409#define UNWRAP(o) \
410 if (PyWeakref_CheckProxy(o)) { \
411 if (!proxy_checkref((PyWeakReference *)o)) \
412 return NULL; \
413 o = PyWeakref_GET_OBJECT(o); \
414 }
415
Fred Drake2a908f62001-12-19 16:44:30 +0000416#define UNWRAP_I(o) \
417 if (PyWeakref_CheckProxy(o)) { \
418 if (!proxy_checkref((PyWeakReference *)o)) \
419 return -1; \
420 o = PyWeakref_GET_OBJECT(o); \
421 }
422
Fred Drake8844d522001-10-05 21:52:26 +0000423#define WRAP_UNARY(method, generic) \
424 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000425 method(PyObject *proxy) { \
426 UNWRAP(proxy); \
427 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000428 }
429
430#define WRAP_BINARY(method, generic) \
431 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000432 method(PyObject *x, PyObject *y) { \
433 UNWRAP(x); \
434 UNWRAP(y); \
435 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000436 }
437
Fred Drake31f4d1f2001-10-18 19:21:46 +0000438/* Note that the third arg needs to be checked for NULL since the tp_call
439 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000440 */
Fred Drake8844d522001-10-05 21:52:26 +0000441#define WRAP_TERNARY(method, generic) \
442 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000443 method(PyObject *proxy, PyObject *v, PyObject *w) { \
444 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000445 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000446 if (w != NULL) \
447 UNWRAP(w); \
448 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000449 }
450
Benjamin Peterson32019772009-11-19 03:08:32 +0000451#define WRAP_METHOD(method, special) \
452 static PyObject * \
453 method(PyObject *proxy) { \
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200454 _Py_IDENTIFIER(special); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000455 UNWRAP(proxy); \
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200456 return _PyObject_CallMethodId(proxy, &PyId_##special, ""); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 }
Benjamin Peterson32019772009-11-19 03:08:32 +0000458
Fred Drake8844d522001-10-05 21:52:26 +0000459
460/* direct slots */
461
462WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
463WRAP_UNARY(proxy_str, PyObject_Str)
464WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
465
Fred Drake8844d522001-10-05 21:52:26 +0000466static PyObject *
467proxy_repr(PyWeakReference *proxy)
468{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100469 return PyUnicode_FromFormat(
470 "<weakproxy at %p to %s at %p>",
471 proxy,
472 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
473 PyWeakref_GET_OBJECT(proxy));
Fred Drake8844d522001-10-05 21:52:26 +0000474}
475
476
477static int
478proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
479{
480 if (!proxy_checkref(proxy))
481 return -1;
482 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
483}
484
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000485static PyObject *
486proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000487{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000488 UNWRAP(proxy);
489 UNWRAP(v);
490 return PyObject_RichCompare(proxy, v, op);
Fred Drake8844d522001-10-05 21:52:26 +0000491}
492
493/* number slots */
494WRAP_BINARY(proxy_add, PyNumber_Add)
495WRAP_BINARY(proxy_sub, PyNumber_Subtract)
496WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000497WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
498WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000499WRAP_BINARY(proxy_mod, PyNumber_Remainder)
500WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
501WRAP_TERNARY(proxy_pow, PyNumber_Power)
502WRAP_UNARY(proxy_neg, PyNumber_Negative)
503WRAP_UNARY(proxy_pos, PyNumber_Positive)
504WRAP_UNARY(proxy_abs, PyNumber_Absolute)
505WRAP_UNARY(proxy_invert, PyNumber_Invert)
506WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
507WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
508WRAP_BINARY(proxy_and, PyNumber_And)
509WRAP_BINARY(proxy_xor, PyNumber_Xor)
510WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000511WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000512WRAP_UNARY(proxy_float, PyNumber_Float)
513WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
514WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
515WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000516WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
517WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000518WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
519WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
520WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
521WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
522WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
523WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
524WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000525WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000526
Tim Peters403a2032003-11-20 21:21:46 +0000527static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000528proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000529{
530 PyObject *o = PyWeakref_GET_OBJECT(proxy);
531 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000532 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000533 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000534}
535
Fred Drake0a4dd392004-07-02 18:57:45 +0000536static void
537proxy_dealloc(PyWeakReference *self)
538{
539 if (self->wr_callback != NULL)
540 PyObject_GC_UnTrack((PyObject *)self);
541 clear_weakref(self);
542 PyObject_GC_Del(self);
543}
544
Fred Drake8844d522001-10-05 21:52:26 +0000545/* sequence slots */
546
Fred Drake8844d522001-10-05 21:52:26 +0000547static int
548proxy_contains(PyWeakReference *proxy, PyObject *value)
549{
550 if (!proxy_checkref(proxy))
551 return -1;
552 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
553}
554
555
556/* mapping slots */
557
Martin v. Löwis18e16552006-02-15 17:27:45 +0000558static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000559proxy_length(PyWeakReference *proxy)
560{
561 if (!proxy_checkref(proxy))
562 return -1;
563 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
564}
565
566WRAP_BINARY(proxy_getitem, PyObject_GetItem)
567
568static int
569proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
570{
571 if (!proxy_checkref(proxy))
572 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000573
574 if (value == NULL)
575 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
576 else
577 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000578}
579
Fred Drakef16c3dc2002-08-09 18:34:16 +0000580/* iterator slots */
581
582static PyObject *
583proxy_iter(PyWeakReference *proxy)
584{
585 if (!proxy_checkref(proxy))
586 return NULL;
587 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
588}
589
590static PyObject *
591proxy_iternext(PyWeakReference *proxy)
592{
593 if (!proxy_checkref(proxy))
594 return NULL;
595 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
596}
597
Fred Drake8844d522001-10-05 21:52:26 +0000598
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200599WRAP_METHOD(proxy_bytes, __bytes__)
Benjamin Peterson32019772009-11-19 03:08:32 +0000600
601
602static PyMethodDef proxy_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603 {"__bytes__", (PyCFunction)proxy_bytes, METH_NOARGS},
604 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000605};
606
607
Fred Drake8844d522001-10-05 21:52:26 +0000608static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000609 proxy_add, /*nb_add*/
610 proxy_sub, /*nb_subtract*/
611 proxy_mul, /*nb_multiply*/
612 proxy_mod, /*nb_remainder*/
613 proxy_divmod, /*nb_divmod*/
614 proxy_pow, /*nb_power*/
615 proxy_neg, /*nb_negative*/
616 proxy_pos, /*nb_positive*/
617 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000618 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000619 proxy_invert, /*nb_invert*/
620 proxy_lshift, /*nb_lshift*/
621 proxy_rshift, /*nb_rshift*/
622 proxy_and, /*nb_and*/
623 proxy_xor, /*nb_xor*/
624 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000625 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000626 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000627 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000628 proxy_iadd, /*nb_inplace_add*/
629 proxy_isub, /*nb_inplace_subtract*/
630 proxy_imul, /*nb_inplace_multiply*/
631 proxy_imod, /*nb_inplace_remainder*/
632 proxy_ipow, /*nb_inplace_power*/
633 proxy_ilshift, /*nb_inplace_lshift*/
634 proxy_irshift, /*nb_inplace_rshift*/
635 proxy_iand, /*nb_inplace_and*/
636 proxy_ixor, /*nb_inplace_xor*/
637 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000638 proxy_floor_div, /*nb_floor_divide*/
639 proxy_true_div, /*nb_true_divide*/
640 proxy_ifloor_div, /*nb_inplace_floor_divide*/
641 proxy_itrue_div, /*nb_inplace_true_divide*/
642 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000643};
644
645static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000646 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000647 0, /*sq_concat*/
648 0, /*sq_repeat*/
649 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000650 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000651 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000652 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000653 (objobjproc)proxy_contains, /* sq_contains */
654};
655
656static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000657 (lenfunc)proxy_length, /*mp_length*/
658 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000659 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
660};
661
662
663PyTypeObject
664_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000665 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000666 "weakproxy",
667 sizeof(PyWeakReference),
668 0,
669 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000670 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 0, /* tp_print */
672 0, /* tp_getattr */
673 0, /* tp_setattr */
674 0, /* tp_reserved */
675 (reprfunc)proxy_repr, /* tp_repr */
676 &proxy_as_number, /* tp_as_number */
677 &proxy_as_sequence, /* tp_as_sequence */
678 &proxy_as_mapping, /* tp_as_mapping */
679 0, /* tp_hash */
680 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000681 proxy_str, /* tp_str */
682 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000683 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000685 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000686 0, /* tp_doc */
687 (traverseproc)gc_traverse, /* tp_traverse */
688 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000689 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000690 0, /* tp_weaklistoffset */
691 (getiterfunc)proxy_iter, /* tp_iter */
692 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000694};
695
696
697PyTypeObject
698_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000699 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000700 "weakcallableproxy",
701 sizeof(PyWeakReference),
702 0,
703 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000704 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000705 0, /* tp_print */
706 0, /* tp_getattr */
707 0, /* tp_setattr */
708 0, /* tp_reserved */
709 (unaryfunc)proxy_repr, /* tp_repr */
710 &proxy_as_number, /* tp_as_number */
711 &proxy_as_sequence, /* tp_as_sequence */
712 &proxy_as_mapping, /* tp_as_mapping */
713 0, /* tp_hash */
714 proxy_call, /* tp_call */
715 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000716 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000717 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000719 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000720 0, /* tp_doc */
721 (traverseproc)gc_traverse, /* tp_traverse */
722 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000723 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000724 0, /* tp_weaklistoffset */
725 (getiterfunc)proxy_iter, /* tp_iter */
726 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000727};
728
729
Fred Drake8844d522001-10-05 21:52:26 +0000730
731PyObject *
732PyWeakref_NewRef(PyObject *ob, PyObject *callback)
733{
734 PyWeakReference *result = NULL;
735 PyWeakReference **list;
736 PyWeakReference *ref, *proxy;
737
Christian Heimes90aa7642007-12-19 02:45:37 +0000738 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000739 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000741 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000742 return NULL;
743 }
744 list = GET_WEAKREFS_LISTPTR(ob);
745 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000746 if (callback == Py_None)
747 callback = NULL;
748 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000749 /* return existing weak reference if it exists */
750 result = ref;
751 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000752 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000753 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000754 /* Note: new_weakref() can trigger cyclic GC, so the weakref
755 list on ob can be mutated. This means that the ref and
756 proxy pointers we got back earlier may have been collected,
757 so we need to compute these values again before we use
758 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000759 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000760 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000761 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000762 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000763 if (ref == NULL)
764 insert_head(result, list);
765 else {
766 /* Someone else added a ref without a callback
767 during GC. Return that one instead of this one
768 to avoid violating the invariants of the list
769 of weakrefs for ob. */
770 Py_DECREF(result);
771 Py_INCREF(ref);
772 result = ref;
773 }
Fred Drake8844d522001-10-05 21:52:26 +0000774 }
775 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000776 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000777
Fred Drakebc875f52004-02-04 23:14:14 +0000778 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000779 if (prev == NULL)
780 insert_head(result, list);
781 else
782 insert_after(result, prev);
783 }
Fred Drake8844d522001-10-05 21:52:26 +0000784 }
785 }
786 return (PyObject *) result;
787}
788
789
790PyObject *
791PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
792{
793 PyWeakReference *result = NULL;
794 PyWeakReference **list;
795 PyWeakReference *ref, *proxy;
796
Christian Heimes90aa7642007-12-19 02:45:37 +0000797 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000798 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000799 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000800 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000801 return NULL;
802 }
803 list = GET_WEAKREFS_LISTPTR(ob);
804 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000805 if (callback == Py_None)
806 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000807 if (callback == NULL)
808 /* attempt to return an existing weak reference if it exists */
809 result = proxy;
810 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000811 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000812 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000813 /* Note: new_weakref() can trigger cyclic GC, so the weakref
814 list on ob can be mutated. This means that the ref and
815 proxy pointers we got back earlier may have been collected,
816 so we need to compute these values again before we use
817 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000818 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000819 if (result != NULL) {
820 PyWeakReference *prev;
821
822 if (PyCallable_Check(ob))
Christian Heimes90aa7642007-12-19 02:45:37 +0000823 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000824 else
Christian Heimes90aa7642007-12-19 02:45:37 +0000825 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000826 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000827 if (callback == NULL) {
828 if (proxy != NULL) {
829 /* Someone else added a proxy without a callback
830 during GC. Return that one instead of this one
831 to avoid violating the invariants of the list
832 of weakrefs for ob. */
833 Py_DECREF(result);
834 Py_INCREF(result = proxy);
835 goto skip_insert;
836 }
Fred Drake8844d522001-10-05 21:52:26 +0000837 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000838 }
Fred Drake8844d522001-10-05 21:52:26 +0000839 else
840 prev = (proxy == NULL) ? ref : proxy;
841
842 if (prev == NULL)
843 insert_head(result, list);
844 else
845 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000846 skip_insert:
847 ;
Fred Drake8844d522001-10-05 21:52:26 +0000848 }
849 }
850 return (PyObject *) result;
851}
852
853
854PyObject *
855PyWeakref_GetObject(PyObject *ref)
856{
857 if (ref == NULL || !PyWeakref_Check(ref)) {
858 PyErr_BadInternalCall();
859 return NULL;
860 }
861 return PyWeakref_GET_OBJECT(ref);
862}
863
Tim Petersead8b7a2004-10-30 23:09:22 +0000864/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
865 * handle_weakrefs().
866 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000867static void
868handle_callback(PyWeakReference *ref, PyObject *callback)
869{
Thomas Wouters477c8d52006-05-27 19:21:47 +0000870 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000871
872 if (cbresult == NULL)
873 PyErr_WriteUnraisable(callback);
874 else
875 Py_DECREF(cbresult);
876}
877
878/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000879 *
880 * This iterates through the weak references for 'object' and calls callbacks
881 * for those references which have one. It returns when all callbacks have
882 * been attempted.
883 */
884void
885PyObject_ClearWeakRefs(PyObject *object)
886{
887 PyWeakReference **list;
888
889 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000890 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000891 || object->ob_refcnt != 0) {
892 PyErr_BadInternalCall();
893 return;
894 }
895 list = GET_WEAKREFS_LISTPTR(object);
896 /* Remove the callback-less basic and proxy references */
897 if (*list != NULL && (*list)->wr_callback == NULL) {
898 clear_weakref(*list);
899 if (*list != NULL && (*list)->wr_callback == NULL)
900 clear_weakref(*list);
901 }
902 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000903 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000904 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000905 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000906
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300907 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000908 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000909 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000910
Fred Drakeef8ebd12001-12-10 23:44:54 +0000911 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000912 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000913 if (callback != NULL) {
Benjamin Petersona38d1562008-06-16 20:47:12 +0000914 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000915 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000916 Py_DECREF(callback);
917 }
Fred Drake8844d522001-10-05 21:52:26 +0000918 }
919 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000920 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000921 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000922
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000923 tuple = PyTuple_New(count * 2);
924 if (tuple == NULL) {
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300925 _PyErr_ChainExceptions(err_type, err_value, err_tb);
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000926 return;
927 }
Fred Drake8844d522001-10-05 21:52:26 +0000928
929 for (i = 0; i < count; ++i) {
930 PyWeakReference *next = current->wr_next;
931
Benjamin Petersona38d1562008-06-16 20:47:12 +0000932 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000933 {
934 Py_INCREF(current);
935 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
936 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
937 }
938 else {
939 Py_DECREF(current->wr_callback);
940 }
Fred Drake8844d522001-10-05 21:52:26 +0000941 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000942 clear_weakref(current);
943 current = next;
944 }
945 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000946 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000947
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000948 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000949 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000950 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
951 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000952 }
Fred Drake8844d522001-10-05 21:52:26 +0000953 }
954 Py_DECREF(tuple);
955 }
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300956 assert(!PyErr_Occurred());
957 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000958 }
959}