blob: ff6d92254f7fe2ca47ed2a868b8a4efb6346c967 [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;
Xiang Zhangd0e82122017-02-20 12:25:16 +080027 self->wr_prev = NULL;
28 self->wr_next = NULL;
Fred Drake0a4dd392004-07-02 18:57:45 +000029 Py_XINCREF(callback);
30 self->wr_callback = callback;
31}
32
Fred Drake8844d522001-10-05 21:52:26 +000033static PyWeakReference *
Neil Schemenauer38a89162002-03-27 15:18:21 +000034new_weakref(PyObject *ob, PyObject *callback)
Fred Drake8844d522001-10-05 21:52:26 +000035{
36 PyWeakReference *result;
37
Neil Schemenauer38a89162002-03-27 15:18:21 +000038 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
39 if (result) {
Fred Drake0a4dd392004-07-02 18:57:45 +000040 init_weakref(result, ob, callback);
Neil Schemenauer38a89162002-03-27 15:18:21 +000041 PyObject_GC_Track(result);
42 }
Fred Drake8844d522001-10-05 21:52:26 +000043 return result;
44}
45
46
47/* This function clears the passed-in reference and removes it from the
48 * list of weak references for the referent. This is the only code that
49 * removes an item from the doubly-linked list of weak references for an
50 * object; it is also responsible for clearing the callback slot.
51 */
52static void
53clear_weakref(PyWeakReference *self)
54{
55 PyObject *callback = self->wr_callback;
56
Antoine Pitrou62a0d6e2012-12-08 21:15:26 +010057 if (self->wr_object != Py_None) {
58 PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
Fred Drake8844d522001-10-05 21:52:26 +000059
60 if (*list == self)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000061 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
62 then the weakref list itself (and thus the value of *list) will
63 end up being set to NULL. */
Fred Drake8844d522001-10-05 21:52:26 +000064 *list = self->wr_next;
65 self->wr_object = Py_None;
Fred Drake8844d522001-10-05 21:52:26 +000066 if (self->wr_prev != NULL)
67 self->wr_prev->wr_next = self->wr_next;
68 if (self->wr_next != NULL)
69 self->wr_next->wr_prev = self->wr_prev;
70 self->wr_prev = NULL;
71 self->wr_next = NULL;
Tim Peters403a2032003-11-20 21:21:46 +000072 }
73 if (callback != NULL) {
74 Py_DECREF(callback);
75 self->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +000076 }
77}
78
Tim Peters403a2032003-11-20 21:21:46 +000079/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
80 * the callback intact and uncalled. It must be possible to call self's
81 * tp_dealloc() after calling this, so self has to be left in a sane enough
82 * state for that to work. We expect tp_dealloc to decref the callback
83 * then. The reason for not letting clear_weakref() decref the callback
84 * right now is that if the callback goes away, that may in turn trigger
85 * another callback (if a weak reference to the callback exists) -- running
86 * arbitrary Python code in the middle of gc is a disaster. The convolution
87 * here allows gc to delay triggering such callbacks until the world is in
88 * a sane state again.
89 */
90void
91_PyWeakref_ClearRef(PyWeakReference *self)
92{
93 PyObject *callback;
94
95 assert(self != NULL);
96 assert(PyWeakref_Check(self));
97 /* Preserve and restore the callback around clear_weakref. */
98 callback = self->wr_callback;
99 self->wr_callback = NULL;
100 clear_weakref(self);
101 self->wr_callback = callback;
102}
Fred Drake8844d522001-10-05 21:52:26 +0000103
104static void
Fred Drake0a4dd392004-07-02 18:57:45 +0000105weakref_dealloc(PyObject *self)
Fred Drake8844d522001-10-05 21:52:26 +0000106{
Fred Drake0a4dd392004-07-02 18:57:45 +0000107 PyObject_GC_UnTrack(self);
108 clear_weakref((PyWeakReference *) self);
Christian Heimes90aa7642007-12-19 02:45:37 +0000109 Py_TYPE(self)->tp_free(self);
Fred Drake8844d522001-10-05 21:52:26 +0000110}
111
112
113static int
114gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
115{
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000116 Py_VISIT(self->wr_callback);
Fred Drake8844d522001-10-05 21:52:26 +0000117 return 0;
118}
119
120
121static int
122gc_clear(PyWeakReference *self)
123{
124 clear_weakref(self);
125 return 0;
126}
127
128
129static PyObject *
130weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
131{
Martin v. Löwis15e62742006-02-27 16:46:16 +0000132 static char *kwlist[] = {NULL};
Fred Drake8844d522001-10-05 21:52:26 +0000133
Martin v. Löwis15e62742006-02-27 16:46:16 +0000134 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
Fred Drake8844d522001-10-05 21:52:26 +0000135 PyObject *object = PyWeakref_GET_OBJECT(self);
136 Py_INCREF(object);
137 return (object);
138 }
139 return NULL;
140}
141
142
Benjamin Peterson8f67d082010-10-17 20:54:53 +0000143static Py_hash_t
Fred Drake8844d522001-10-05 21:52:26 +0000144weakref_hash(PyWeakReference *self)
145{
146 if (self->hash != -1)
147 return self->hash;
148 if (PyWeakref_GET_OBJECT(self) == Py_None) {
149 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
150 return -1;
151 }
152 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
153 return self->hash;
154}
Tim Peters403a2032003-11-20 21:21:46 +0000155
Fred Drake8844d522001-10-05 21:52:26 +0000156
157static PyObject *
158weakref_repr(PyWeakReference *self)
159{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100160 PyObject *name, *repr;
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200161 _Py_IDENTIFIER(__name__);
Victor Stinner499dfcf2011-03-21 13:26:24 +0100162
163 if (PyWeakref_GET_OBJECT(self) == Py_None)
164 return PyUnicode_FromFormat("<weakref at %p; dead>", self);
165
Martin v. Löwis1ee1b6f2011-10-10 18:11:30 +0200166 name = _PyObject_GetAttrId(PyWeakref_GET_OBJECT(self), &PyId___name__);
Victor Stinner499dfcf2011-03-21 13:26:24 +0100167 if (name == NULL || !PyUnicode_Check(name)) {
168 if (name == NULL)
169 PyErr_Clear();
170 repr = PyUnicode_FromFormat(
171 "<weakref at %p; to '%s' at %p>",
172 self,
173 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
174 PyWeakref_GET_OBJECT(self));
Fred Drake8844d522001-10-05 21:52:26 +0000175 }
176 else {
Victor Stinner499dfcf2011-03-21 13:26:24 +0100177 repr = PyUnicode_FromFormat(
178 "<weakref at %p; to '%s' at %p (%U)>",
179 self,
180 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
181 PyWeakref_GET_OBJECT(self),
182 name);
Fred Drake8844d522001-10-05 21:52:26 +0000183 }
Victor Stinner499dfcf2011-03-21 13:26:24 +0100184 Py_XDECREF(name);
185 return repr;
Fred Drake8844d522001-10-05 21:52:26 +0000186}
187
188/* Weak references only support equality, not ordering. Two weak references
189 are equal if the underlying objects are equal. If the underlying object has
190 gone away, they are equal if they are identical. */
191
192static PyObject *
193weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
194{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000195 if ((op != Py_EQ && op != Py_NE) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000196 !PyWeakref_Check(self) ||
197 !PyWeakref_Check(other)) {
Brian Curtindfc80e32011-08-10 20:28:54 -0500198 Py_RETURN_NOTIMPLEMENTED;
Fred Drake8844d522001-10-05 21:52:26 +0000199 }
200 if (PyWeakref_GET_OBJECT(self) == Py_None
201 || PyWeakref_GET_OBJECT(other) == Py_None) {
Antoine Pitroue11fecb2012-11-11 19:36:51 +0100202 int res = (self == other);
203 if (op == Py_NE)
204 res = !res;
205 if (res)
206 Py_RETURN_TRUE;
207 else
208 Py_RETURN_FALSE;
Fred Drake8844d522001-10-05 21:52:26 +0000209 }
210 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
211 PyWeakref_GET_OBJECT(other), op);
212}
213
Fred Drake0a4dd392004-07-02 18:57:45 +0000214/* Given the head of an object's list of weak references, extract the
215 * two callback-less refs (ref and proxy). Used to determine if the
216 * shared references exist and to determine the back link for newly
217 * inserted references.
218 */
219static void
220get_basic_refs(PyWeakReference *head,
221 PyWeakReference **refp, PyWeakReference **proxyp)
222{
223 *refp = NULL;
224 *proxyp = NULL;
225
226 if (head != NULL && head->wr_callback == NULL) {
227 /* We need to be careful that the "basic refs" aren't
228 subclasses of the main types. That complicates this a
229 little. */
230 if (PyWeakref_CheckRefExact(head)) {
231 *refp = head;
232 head = head->wr_next;
233 }
234 if (head != NULL
235 && head->wr_callback == NULL
236 && PyWeakref_CheckProxy(head)) {
237 *proxyp = head;
238 /* head = head->wr_next; */
239 }
240 }
241}
242
243/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
244static void
245insert_after(PyWeakReference *newref, PyWeakReference *prev)
246{
247 newref->wr_prev = prev;
248 newref->wr_next = prev->wr_next;
249 if (prev->wr_next != NULL)
250 prev->wr_next->wr_prev = newref;
251 prev->wr_next = newref;
252}
253
254/* Insert 'newref' at the head of the list; 'list' points to the variable
255 * that stores the head.
256 */
257static void
258insert_head(PyWeakReference *newref, PyWeakReference **list)
259{
260 PyWeakReference *next = *list;
261
262 newref->wr_prev = NULL;
263 newref->wr_next = next;
264 if (next != NULL)
265 next->wr_prev = newref;
266 *list = newref;
267}
268
269static int
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200270parse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs,
Fred Drake0a4dd392004-07-02 18:57:45 +0000271 PyObject **obp, PyObject **callbackp)
272{
Fred Drake0a4dd392004-07-02 18:57:45 +0000273 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
274}
275
276static PyObject *
277weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
278{
279 PyWeakReference *self = NULL;
280 PyObject *ob, *callback = NULL;
281
282 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
283 PyWeakReference *ref, *proxy;
284 PyWeakReference **list;
285
Christian Heimes90aa7642007-12-19 02:45:37 +0000286 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000287 PyErr_Format(PyExc_TypeError,
288 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000289 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000290 return NULL;
291 }
292 if (callback == Py_None)
293 callback = NULL;
294 list = GET_WEAKREFS_LISTPTR(ob);
295 get_basic_refs(*list, &ref, &proxy);
296 if (callback == NULL && type == &_PyWeakref_RefType) {
297 if (ref != NULL) {
298 /* We can re-use an existing reference. */
299 Py_INCREF(ref);
300 return (PyObject *)ref;
301 }
302 }
303 /* We have to create a new reference. */
304 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
305 list on ob can be mutated. This means that the ref and
306 proxy pointers we got back earlier may have been collected,
307 so we need to compute these values again before we use
308 them. */
309 self = (PyWeakReference *) (type->tp_alloc(type, 0));
310 if (self != NULL) {
311 init_weakref(self, ob, callback);
312 if (callback == NULL && type == &_PyWeakref_RefType) {
313 insert_head(self, list);
314 }
315 else {
316 PyWeakReference *prev;
317
318 get_basic_refs(*list, &ref, &proxy);
319 prev = (proxy == NULL) ? ref : proxy;
320 if (prev == NULL)
321 insert_head(self, list);
322 else
323 insert_after(self, prev);
324 }
325 }
326 }
327 return (PyObject *)self;
328}
329
330static int
331weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
332{
333 PyObject *tmp;
334
Serhiy Storchaka6cca5c82017-06-08 14:41:19 +0300335 if (!_PyArg_NoKeywords("ref", kwargs))
Serhiy Storchaka21eb4872016-05-07 15:41:09 +0300336 return -1;
337
Fred Drake0a4dd392004-07-02 18:57:45 +0000338 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
339 return 0;
340 else
Benjamin Peterson9aa42992008-09-10 21:57:34 +0000341 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000342}
343
Fred Drake8844d522001-10-05 21:52:26 +0000344
Mark Dickinson556e94b2013-04-13 15:45:44 +0100345static PyMemberDef weakref_members[] = {
346 {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY},
347 {NULL} /* Sentinel */
348};
349
Fred Drake8844d522001-10-05 21:52:26 +0000350PyTypeObject
351_PyWeakref_RefType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000352 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000353 "weakref",
354 sizeof(PyWeakReference),
355 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000356 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000357 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000358 0, /*tp_getattr*/
359 0, /*tp_setattr*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000360 0, /*tp_reserved*/
Fred Drake8844d522001-10-05 21:52:26 +0000361 (reprfunc)weakref_repr, /*tp_repr*/
362 0, /*tp_as_number*/
363 0, /*tp_as_sequence*/
364 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000365 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000366 (ternaryfunc)weakref_call, /*tp_call*/
367 0, /*tp_str*/
368 0, /*tp_getattro*/
369 0, /*tp_setattro*/
370 0, /*tp_as_buffer*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000371 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000372 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000373 0, /*tp_doc*/
374 (traverseproc)gc_traverse, /*tp_traverse*/
375 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000377 0, /*tp_weaklistoffset*/
378 0, /*tp_iter*/
379 0, /*tp_iternext*/
380 0, /*tp_methods*/
Mark Dickinson556e94b2013-04-13 15:45:44 +0100381 weakref_members, /*tp_members*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000382 0, /*tp_getset*/
383 0, /*tp_base*/
384 0, /*tp_dict*/
385 0, /*tp_descr_get*/
386 0, /*tp_descr_set*/
387 0, /*tp_dictoffset*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000388 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000389 PyType_GenericAlloc, /*tp_alloc*/
390 weakref___new__, /*tp_new*/
391 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000392};
393
394
395static int
396proxy_checkref(PyWeakReference *proxy)
397{
398 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
399 PyErr_SetString(PyExc_ReferenceError,
400 "weakly-referenced object no longer exists");
401 return 0;
402 }
403 return 1;
404}
405
406
Fred Drake73006d02001-10-18 18:04:18 +0000407/* If a parameter is a proxy, check that it is still "live" and wrap it,
408 * replacing the original value with the raw object. Raises ReferenceError
409 * if the param is a dead proxy.
410 */
411#define UNWRAP(o) \
412 if (PyWeakref_CheckProxy(o)) { \
413 if (!proxy_checkref((PyWeakReference *)o)) \
414 return NULL; \
415 o = PyWeakref_GET_OBJECT(o); \
416 }
417
Fred Drake2a908f62001-12-19 16:44:30 +0000418#define UNWRAP_I(o) \
419 if (PyWeakref_CheckProxy(o)) { \
420 if (!proxy_checkref((PyWeakReference *)o)) \
421 return -1; \
422 o = PyWeakref_GET_OBJECT(o); \
423 }
424
Fred Drake8844d522001-10-05 21:52:26 +0000425#define WRAP_UNARY(method, generic) \
426 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000427 method(PyObject *proxy) { \
428 UNWRAP(proxy); \
429 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000430 }
431
432#define WRAP_BINARY(method, generic) \
433 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000434 method(PyObject *x, PyObject *y) { \
435 UNWRAP(x); \
436 UNWRAP(y); \
437 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000438 }
439
Fred Drake31f4d1f2001-10-18 19:21:46 +0000440/* Note that the third arg needs to be checked for NULL since the tp_call
441 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000442 */
Fred Drake8844d522001-10-05 21:52:26 +0000443#define WRAP_TERNARY(method, generic) \
444 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000445 method(PyObject *proxy, PyObject *v, PyObject *w) { \
446 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000447 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000448 if (w != NULL) \
449 UNWRAP(w); \
450 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000451 }
452
Benjamin Peterson32019772009-11-19 03:08:32 +0000453#define WRAP_METHOD(method, special) \
454 static PyObject * \
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530455 method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200456 _Py_IDENTIFIER(special); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 UNWRAP(proxy); \
Victor Stinner3466bde2016-09-05 18:16:01 -0700458 return _PyObject_CallMethodId(proxy, &PyId_##special, NULL); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000459 }
Benjamin Peterson32019772009-11-19 03:08:32 +0000460
Fred Drake8844d522001-10-05 21:52:26 +0000461
462/* direct slots */
463
464WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
465WRAP_UNARY(proxy_str, PyObject_Str)
INADA Naoki72dccde2017-02-16 09:26:01 +0900466WRAP_TERNARY(proxy_call, PyObject_Call)
Fred Drake8844d522001-10-05 21:52:26 +0000467
Fred Drake8844d522001-10-05 21:52:26 +0000468static PyObject *
469proxy_repr(PyWeakReference *proxy)
470{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100471 return PyUnicode_FromFormat(
472 "<weakproxy at %p to %s at %p>",
473 proxy,
474 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
475 PyWeakref_GET_OBJECT(proxy));
Fred Drake8844d522001-10-05 21:52:26 +0000476}
477
478
479static int
480proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
481{
482 if (!proxy_checkref(proxy))
483 return -1;
484 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
485}
486
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000487static PyObject *
488proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000489{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000490 UNWRAP(proxy);
491 UNWRAP(v);
492 return PyObject_RichCompare(proxy, v, op);
Fred Drake8844d522001-10-05 21:52:26 +0000493}
494
495/* number slots */
496WRAP_BINARY(proxy_add, PyNumber_Add)
497WRAP_BINARY(proxy_sub, PyNumber_Subtract)
498WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000499WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
500WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000501WRAP_BINARY(proxy_mod, PyNumber_Remainder)
502WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
503WRAP_TERNARY(proxy_pow, PyNumber_Power)
504WRAP_UNARY(proxy_neg, PyNumber_Negative)
505WRAP_UNARY(proxy_pos, PyNumber_Positive)
506WRAP_UNARY(proxy_abs, PyNumber_Absolute)
507WRAP_UNARY(proxy_invert, PyNumber_Invert)
508WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
509WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
510WRAP_BINARY(proxy_and, PyNumber_And)
511WRAP_BINARY(proxy_xor, PyNumber_Xor)
512WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000513WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000514WRAP_UNARY(proxy_float, PyNumber_Float)
515WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
516WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
517WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000518WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
519WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000520WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
521WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
522WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
523WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
524WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
525WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
526WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000527WRAP_UNARY(proxy_index, PyNumber_Index)
Mark Dickinson7abb6c02019-04-26 15:56:15 +0900528WRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply)
529WRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply)
Fred Drake8844d522001-10-05 21:52:26 +0000530
Tim Peters403a2032003-11-20 21:21:46 +0000531static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000532proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000533{
534 PyObject *o = PyWeakref_GET_OBJECT(proxy);
535 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000536 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000537 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000538}
539
Fred Drake0a4dd392004-07-02 18:57:45 +0000540static void
541proxy_dealloc(PyWeakReference *self)
542{
543 if (self->wr_callback != NULL)
544 PyObject_GC_UnTrack((PyObject *)self);
545 clear_weakref(self);
546 PyObject_GC_Del(self);
547}
548
Fred Drake8844d522001-10-05 21:52:26 +0000549/* sequence slots */
550
Fred Drake8844d522001-10-05 21:52:26 +0000551static int
552proxy_contains(PyWeakReference *proxy, PyObject *value)
553{
554 if (!proxy_checkref(proxy))
555 return -1;
556 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
557}
558
559
560/* mapping slots */
561
Martin v. Löwis18e16552006-02-15 17:27:45 +0000562static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000563proxy_length(PyWeakReference *proxy)
564{
565 if (!proxy_checkref(proxy))
566 return -1;
567 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
568}
569
570WRAP_BINARY(proxy_getitem, PyObject_GetItem)
571
572static int
573proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
574{
575 if (!proxy_checkref(proxy))
576 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000577
578 if (value == NULL)
579 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
580 else
581 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000582}
583
Fred Drakef16c3dc2002-08-09 18:34:16 +0000584/* iterator slots */
585
586static PyObject *
587proxy_iter(PyWeakReference *proxy)
588{
589 if (!proxy_checkref(proxy))
590 return NULL;
591 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
592}
593
594static PyObject *
595proxy_iternext(PyWeakReference *proxy)
596{
597 if (!proxy_checkref(proxy))
598 return NULL;
599 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
600}
601
Fred Drake8844d522001-10-05 21:52:26 +0000602
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200603WRAP_METHOD(proxy_bytes, __bytes__)
Benjamin Peterson32019772009-11-19 03:08:32 +0000604
605
606static PyMethodDef proxy_methods[] = {
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530607 {"__bytes__", proxy_bytes, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000609};
610
611
Fred Drake8844d522001-10-05 21:52:26 +0000612static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000613 proxy_add, /*nb_add*/
614 proxy_sub, /*nb_subtract*/
615 proxy_mul, /*nb_multiply*/
616 proxy_mod, /*nb_remainder*/
617 proxy_divmod, /*nb_divmod*/
618 proxy_pow, /*nb_power*/
619 proxy_neg, /*nb_negative*/
620 proxy_pos, /*nb_positive*/
621 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000622 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000623 proxy_invert, /*nb_invert*/
624 proxy_lshift, /*nb_lshift*/
625 proxy_rshift, /*nb_rshift*/
626 proxy_and, /*nb_and*/
627 proxy_xor, /*nb_xor*/
628 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000629 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000630 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000631 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000632 proxy_iadd, /*nb_inplace_add*/
633 proxy_isub, /*nb_inplace_subtract*/
634 proxy_imul, /*nb_inplace_multiply*/
635 proxy_imod, /*nb_inplace_remainder*/
636 proxy_ipow, /*nb_inplace_power*/
637 proxy_ilshift, /*nb_inplace_lshift*/
638 proxy_irshift, /*nb_inplace_rshift*/
639 proxy_iand, /*nb_inplace_and*/
640 proxy_ixor, /*nb_inplace_xor*/
641 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000642 proxy_floor_div, /*nb_floor_divide*/
643 proxy_true_div, /*nb_true_divide*/
644 proxy_ifloor_div, /*nb_inplace_floor_divide*/
645 proxy_itrue_div, /*nb_inplace_true_divide*/
646 proxy_index, /*nb_index*/
Mark Dickinson7abb6c02019-04-26 15:56:15 +0900647 proxy_matmul, /*nb_matrix_multiply*/
648 proxy_imatmul, /*nb_inplace_matrix_multiply*/
Fred Drake8844d522001-10-05 21:52:26 +0000649};
650
651static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000652 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000653 0, /*sq_concat*/
654 0, /*sq_repeat*/
655 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000656 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000657 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000659 (objobjproc)proxy_contains, /* sq_contains */
660};
661
662static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000663 (lenfunc)proxy_length, /*mp_length*/
664 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000665 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
666};
667
668
669PyTypeObject
670_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000671 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000672 "weakproxy",
673 sizeof(PyWeakReference),
674 0,
675 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000676 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 0, /* tp_print */
678 0, /* tp_getattr */
679 0, /* tp_setattr */
680 0, /* tp_reserved */
681 (reprfunc)proxy_repr, /* tp_repr */
682 &proxy_as_number, /* tp_as_number */
683 &proxy_as_sequence, /* tp_as_sequence */
684 &proxy_as_mapping, /* tp_as_mapping */
685 0, /* tp_hash */
686 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000687 proxy_str, /* tp_str */
688 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000689 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000691 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000692 0, /* tp_doc */
693 (traverseproc)gc_traverse, /* tp_traverse */
694 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000695 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000696 0, /* tp_weaklistoffset */
697 (getiterfunc)proxy_iter, /* tp_iter */
698 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000699 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000700};
701
702
703PyTypeObject
704_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000705 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000706 "weakcallableproxy",
707 sizeof(PyWeakReference),
708 0,
709 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000710 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000711 0, /* tp_print */
712 0, /* tp_getattr */
713 0, /* tp_setattr */
714 0, /* tp_reserved */
715 (unaryfunc)proxy_repr, /* tp_repr */
716 &proxy_as_number, /* tp_as_number */
717 &proxy_as_sequence, /* tp_as_sequence */
718 &proxy_as_mapping, /* tp_as_mapping */
719 0, /* tp_hash */
720 proxy_call, /* tp_call */
721 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000722 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000723 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000724 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000725 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000726 0, /* tp_doc */
727 (traverseproc)gc_traverse, /* tp_traverse */
728 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000729 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000730 0, /* tp_weaklistoffset */
731 (getiterfunc)proxy_iter, /* tp_iter */
732 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000733};
734
735
Fred Drake8844d522001-10-05 21:52:26 +0000736
737PyObject *
738PyWeakref_NewRef(PyObject *ob, PyObject *callback)
739{
740 PyWeakReference *result = NULL;
741 PyWeakReference **list;
742 PyWeakReference *ref, *proxy;
743
Christian Heimes90aa7642007-12-19 02:45:37 +0000744 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000745 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000746 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000747 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000748 return NULL;
749 }
750 list = GET_WEAKREFS_LISTPTR(ob);
751 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000752 if (callback == Py_None)
753 callback = NULL;
754 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000755 /* return existing weak reference if it exists */
756 result = ref;
757 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000758 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000759 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000760 /* Note: new_weakref() can trigger cyclic GC, so the weakref
761 list on ob can be mutated. This means that the ref and
762 proxy pointers we got back earlier may have been collected,
763 so we need to compute these values again before we use
764 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000765 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000766 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000767 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000768 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000769 if (ref == NULL)
770 insert_head(result, list);
771 else {
772 /* Someone else added a ref without a callback
773 during GC. Return that one instead of this one
774 to avoid violating the invariants of the list
775 of weakrefs for ob. */
776 Py_DECREF(result);
777 Py_INCREF(ref);
778 result = ref;
779 }
Fred Drake8844d522001-10-05 21:52:26 +0000780 }
781 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000782 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000783
Fred Drakebc875f52004-02-04 23:14:14 +0000784 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000785 if (prev == NULL)
786 insert_head(result, list);
787 else
788 insert_after(result, prev);
789 }
Fred Drake8844d522001-10-05 21:52:26 +0000790 }
791 }
792 return (PyObject *) result;
793}
794
795
796PyObject *
797PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
798{
799 PyWeakReference *result = NULL;
800 PyWeakReference **list;
801 PyWeakReference *ref, *proxy;
802
Christian Heimes90aa7642007-12-19 02:45:37 +0000803 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000804 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000805 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000806 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000807 return NULL;
808 }
809 list = GET_WEAKREFS_LISTPTR(ob);
810 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000811 if (callback == Py_None)
812 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000813 if (callback == NULL)
814 /* attempt to return an existing weak reference if it exists */
815 result = proxy;
816 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000817 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000818 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000819 /* Note: new_weakref() can trigger cyclic GC, so the weakref
820 list on ob can be mutated. This means that the ref and
821 proxy pointers we got back earlier may have been collected,
822 so we need to compute these values again before we use
823 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000824 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000825 if (result != NULL) {
826 PyWeakReference *prev;
827
828 if (PyCallable_Check(ob))
Christian Heimes90aa7642007-12-19 02:45:37 +0000829 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000830 else
Christian Heimes90aa7642007-12-19 02:45:37 +0000831 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000832 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000833 if (callback == NULL) {
834 if (proxy != NULL) {
835 /* Someone else added a proxy without a callback
836 during GC. Return that one instead of this one
837 to avoid violating the invariants of the list
838 of weakrefs for ob. */
839 Py_DECREF(result);
Victor Stinnerb37672d2018-11-22 03:37:50 +0100840 result = proxy;
841 Py_INCREF(result);
Fred Drake6d3265d2004-08-03 14:47:25 +0000842 goto skip_insert;
843 }
Fred Drake8844d522001-10-05 21:52:26 +0000844 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000845 }
Fred Drake8844d522001-10-05 21:52:26 +0000846 else
847 prev = (proxy == NULL) ? ref : proxy;
848
849 if (prev == NULL)
850 insert_head(result, list);
851 else
852 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000853 skip_insert:
854 ;
Fred Drake8844d522001-10-05 21:52:26 +0000855 }
856 }
857 return (PyObject *) result;
858}
859
860
861PyObject *
862PyWeakref_GetObject(PyObject *ref)
863{
864 if (ref == NULL || !PyWeakref_Check(ref)) {
865 PyErr_BadInternalCall();
866 return NULL;
867 }
868 return PyWeakref_GET_OBJECT(ref);
869}
870
Tim Petersead8b7a2004-10-30 23:09:22 +0000871/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
872 * handle_weakrefs().
873 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000874static void
875handle_callback(PyWeakReference *ref, PyObject *callback)
876{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +0100877 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000878
879 if (cbresult == NULL)
880 PyErr_WriteUnraisable(callback);
881 else
882 Py_DECREF(cbresult);
883}
884
885/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000886 *
887 * This iterates through the weak references for 'object' and calls callbacks
888 * for those references which have one. It returns when all callbacks have
889 * been attempted.
890 */
891void
892PyObject_ClearWeakRefs(PyObject *object)
893{
894 PyWeakReference **list;
895
896 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000897 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000898 || object->ob_refcnt != 0) {
899 PyErr_BadInternalCall();
900 return;
901 }
902 list = GET_WEAKREFS_LISTPTR(object);
903 /* Remove the callback-less basic and proxy references */
904 if (*list != NULL && (*list)->wr_callback == NULL) {
905 clear_weakref(*list);
906 if (*list != NULL && (*list)->wr_callback == NULL)
907 clear_weakref(*list);
908 }
909 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000910 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000911 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000912 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000913
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300914 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000915 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000916 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000917
Fred Drakeef8ebd12001-12-10 23:44:54 +0000918 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000919 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000920 if (callback != NULL) {
Benjamin Petersona38d1562008-06-16 20:47:12 +0000921 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000922 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000923 Py_DECREF(callback);
924 }
Fred Drake8844d522001-10-05 21:52:26 +0000925 }
926 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000927 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000928 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000929
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000930 tuple = PyTuple_New(count * 2);
931 if (tuple == NULL) {
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300932 _PyErr_ChainExceptions(err_type, err_value, err_tb);
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000933 return;
934 }
Fred Drake8844d522001-10-05 21:52:26 +0000935
936 for (i = 0; i < count; ++i) {
937 PyWeakReference *next = current->wr_next;
938
Benjamin Petersona38d1562008-06-16 20:47:12 +0000939 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000940 {
941 Py_INCREF(current);
942 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
943 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
944 }
945 else {
946 Py_DECREF(current->wr_callback);
947 }
Fred Drake8844d522001-10-05 21:52:26 +0000948 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000949 clear_weakref(current);
950 current = next;
951 }
952 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000953 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000954
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000955 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000956 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000957 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
958 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000959 }
Fred Drake8844d522001-10-05 21:52:26 +0000960 }
961 Py_DECREF(tuple);
962 }
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300963 assert(!PyErr_Occurred());
964 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000965 }
966}