blob: c083f8fce5e870055c913d378cb857d454d6022a [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
Mark Dickinson556e94b2013-04-13 15:45:44 +0100341static PyMemberDef weakref_members[] = {
342 {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY},
343 {NULL} /* Sentinel */
344};
345
Fred Drake8844d522001-10-05 21:52:26 +0000346PyTypeObject
347_PyWeakref_RefType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000348 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000349 "weakref",
350 sizeof(PyWeakReference),
351 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000352 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000353 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000354 0, /*tp_getattr*/
355 0, /*tp_setattr*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356 0, /*tp_reserved*/
Fred Drake8844d522001-10-05 21:52:26 +0000357 (reprfunc)weakref_repr, /*tp_repr*/
358 0, /*tp_as_number*/
359 0, /*tp_as_sequence*/
360 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000361 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000362 (ternaryfunc)weakref_call, /*tp_call*/
363 0, /*tp_str*/
364 0, /*tp_getattro*/
365 0, /*tp_setattro*/
366 0, /*tp_as_buffer*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000367 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000368 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000369 0, /*tp_doc*/
370 (traverseproc)gc_traverse, /*tp_traverse*/
371 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000372 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000373 0, /*tp_weaklistoffset*/
374 0, /*tp_iter*/
375 0, /*tp_iternext*/
376 0, /*tp_methods*/
Mark Dickinson556e94b2013-04-13 15:45:44 +0100377 weakref_members, /*tp_members*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000378 0, /*tp_getset*/
379 0, /*tp_base*/
380 0, /*tp_dict*/
381 0, /*tp_descr_get*/
382 0, /*tp_descr_set*/
383 0, /*tp_dictoffset*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000384 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000385 PyType_GenericAlloc, /*tp_alloc*/
386 weakref___new__, /*tp_new*/
387 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000388};
389
390
391static int
392proxy_checkref(PyWeakReference *proxy)
393{
394 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
395 PyErr_SetString(PyExc_ReferenceError,
396 "weakly-referenced object no longer exists");
397 return 0;
398 }
399 return 1;
400}
401
402
Fred Drake73006d02001-10-18 18:04:18 +0000403/* If a parameter is a proxy, check that it is still "live" and wrap it,
404 * replacing the original value with the raw object. Raises ReferenceError
405 * if the param is a dead proxy.
406 */
407#define UNWRAP(o) \
408 if (PyWeakref_CheckProxy(o)) { \
409 if (!proxy_checkref((PyWeakReference *)o)) \
410 return NULL; \
411 o = PyWeakref_GET_OBJECT(o); \
412 }
413
Fred Drake2a908f62001-12-19 16:44:30 +0000414#define UNWRAP_I(o) \
415 if (PyWeakref_CheckProxy(o)) { \
416 if (!proxy_checkref((PyWeakReference *)o)) \
417 return -1; \
418 o = PyWeakref_GET_OBJECT(o); \
419 }
420
Fred Drake8844d522001-10-05 21:52:26 +0000421#define WRAP_UNARY(method, generic) \
422 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000423 method(PyObject *proxy) { \
424 UNWRAP(proxy); \
425 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000426 }
427
428#define WRAP_BINARY(method, generic) \
429 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000430 method(PyObject *x, PyObject *y) { \
431 UNWRAP(x); \
432 UNWRAP(y); \
433 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000434 }
435
Fred Drake31f4d1f2001-10-18 19:21:46 +0000436/* Note that the third arg needs to be checked for NULL since the tp_call
437 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000438 */
Fred Drake8844d522001-10-05 21:52:26 +0000439#define WRAP_TERNARY(method, generic) \
440 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000441 method(PyObject *proxy, PyObject *v, PyObject *w) { \
442 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000443 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000444 if (w != NULL) \
445 UNWRAP(w); \
446 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000447 }
448
Benjamin Peterson32019772009-11-19 03:08:32 +0000449#define WRAP_METHOD(method, special) \
450 static PyObject * \
451 method(PyObject *proxy) { \
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200452 _Py_IDENTIFIER(special); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000453 UNWRAP(proxy); \
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200454 return _PyObject_CallMethodId(proxy, &PyId_##special, ""); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000455 }
Benjamin Peterson32019772009-11-19 03:08:32 +0000456
Fred Drake8844d522001-10-05 21:52:26 +0000457
458/* direct slots */
459
460WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
461WRAP_UNARY(proxy_str, PyObject_Str)
462WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
463
Fred Drake8844d522001-10-05 21:52:26 +0000464static PyObject *
465proxy_repr(PyWeakReference *proxy)
466{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100467 return PyUnicode_FromFormat(
468 "<weakproxy at %p to %s at %p>",
469 proxy,
470 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
471 PyWeakref_GET_OBJECT(proxy));
Fred Drake8844d522001-10-05 21:52:26 +0000472}
473
474
475static int
476proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
477{
478 if (!proxy_checkref(proxy))
479 return -1;
480 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
481}
482
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000483static PyObject *
484proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000485{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000486 UNWRAP(proxy);
487 UNWRAP(v);
488 return PyObject_RichCompare(proxy, v, op);
Fred Drake8844d522001-10-05 21:52:26 +0000489}
490
491/* number slots */
492WRAP_BINARY(proxy_add, PyNumber_Add)
493WRAP_BINARY(proxy_sub, PyNumber_Subtract)
494WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000495WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
496WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000497WRAP_BINARY(proxy_mod, PyNumber_Remainder)
498WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
499WRAP_TERNARY(proxy_pow, PyNumber_Power)
500WRAP_UNARY(proxy_neg, PyNumber_Negative)
501WRAP_UNARY(proxy_pos, PyNumber_Positive)
502WRAP_UNARY(proxy_abs, PyNumber_Absolute)
503WRAP_UNARY(proxy_invert, PyNumber_Invert)
504WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
505WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
506WRAP_BINARY(proxy_and, PyNumber_And)
507WRAP_BINARY(proxy_xor, PyNumber_Xor)
508WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000509WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000510WRAP_UNARY(proxy_float, PyNumber_Float)
511WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
512WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
513WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000514WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
515WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000516WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
517WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
518WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
519WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
520WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
521WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
522WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000523WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000524
Tim Peters403a2032003-11-20 21:21:46 +0000525static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000526proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000527{
528 PyObject *o = PyWeakref_GET_OBJECT(proxy);
529 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000530 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000531 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000532}
533
Fred Drake0a4dd392004-07-02 18:57:45 +0000534static void
535proxy_dealloc(PyWeakReference *self)
536{
537 if (self->wr_callback != NULL)
538 PyObject_GC_UnTrack((PyObject *)self);
539 clear_weakref(self);
540 PyObject_GC_Del(self);
541}
542
Fred Drake8844d522001-10-05 21:52:26 +0000543/* sequence slots */
544
Fred Drake8844d522001-10-05 21:52:26 +0000545static int
546proxy_contains(PyWeakReference *proxy, PyObject *value)
547{
548 if (!proxy_checkref(proxy))
549 return -1;
550 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
551}
552
553
554/* mapping slots */
555
Martin v. Löwis18e16552006-02-15 17:27:45 +0000556static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000557proxy_length(PyWeakReference *proxy)
558{
559 if (!proxy_checkref(proxy))
560 return -1;
561 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
562}
563
564WRAP_BINARY(proxy_getitem, PyObject_GetItem)
565
566static int
567proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
568{
569 if (!proxy_checkref(proxy))
570 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000571
572 if (value == NULL)
573 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
574 else
575 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000576}
577
Fred Drakef16c3dc2002-08-09 18:34:16 +0000578/* iterator slots */
579
580static PyObject *
581proxy_iter(PyWeakReference *proxy)
582{
583 if (!proxy_checkref(proxy))
584 return NULL;
585 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
586}
587
588static PyObject *
589proxy_iternext(PyWeakReference *proxy)
590{
591 if (!proxy_checkref(proxy))
592 return NULL;
593 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
594}
595
Fred Drake8844d522001-10-05 21:52:26 +0000596
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200597WRAP_METHOD(proxy_bytes, __bytes__)
Benjamin Peterson32019772009-11-19 03:08:32 +0000598
599
600static PyMethodDef proxy_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 {"__bytes__", (PyCFunction)proxy_bytes, METH_NOARGS},
602 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000603};
604
605
Fred Drake8844d522001-10-05 21:52:26 +0000606static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000607 proxy_add, /*nb_add*/
608 proxy_sub, /*nb_subtract*/
609 proxy_mul, /*nb_multiply*/
610 proxy_mod, /*nb_remainder*/
611 proxy_divmod, /*nb_divmod*/
612 proxy_pow, /*nb_power*/
613 proxy_neg, /*nb_negative*/
614 proxy_pos, /*nb_positive*/
615 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000616 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000617 proxy_invert, /*nb_invert*/
618 proxy_lshift, /*nb_lshift*/
619 proxy_rshift, /*nb_rshift*/
620 proxy_and, /*nb_and*/
621 proxy_xor, /*nb_xor*/
622 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000623 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000624 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000625 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000626 proxy_iadd, /*nb_inplace_add*/
627 proxy_isub, /*nb_inplace_subtract*/
628 proxy_imul, /*nb_inplace_multiply*/
629 proxy_imod, /*nb_inplace_remainder*/
630 proxy_ipow, /*nb_inplace_power*/
631 proxy_ilshift, /*nb_inplace_lshift*/
632 proxy_irshift, /*nb_inplace_rshift*/
633 proxy_iand, /*nb_inplace_and*/
634 proxy_ixor, /*nb_inplace_xor*/
635 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000636 proxy_floor_div, /*nb_floor_divide*/
637 proxy_true_div, /*nb_true_divide*/
638 proxy_ifloor_div, /*nb_inplace_floor_divide*/
639 proxy_itrue_div, /*nb_inplace_true_divide*/
640 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000641};
642
643static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000644 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000645 0, /*sq_concat*/
646 0, /*sq_repeat*/
647 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000648 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000649 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000651 (objobjproc)proxy_contains, /* sq_contains */
652};
653
654static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000655 (lenfunc)proxy_length, /*mp_length*/
656 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000657 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
658};
659
660
661PyTypeObject
662_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000663 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000664 "weakproxy",
665 sizeof(PyWeakReference),
666 0,
667 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000668 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 0, /* tp_print */
670 0, /* tp_getattr */
671 0, /* tp_setattr */
672 0, /* tp_reserved */
673 (reprfunc)proxy_repr, /* tp_repr */
674 &proxy_as_number, /* tp_as_number */
675 &proxy_as_sequence, /* tp_as_sequence */
676 &proxy_as_mapping, /* tp_as_mapping */
677 0, /* tp_hash */
678 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000679 proxy_str, /* tp_str */
680 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000681 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000683 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000684 0, /* tp_doc */
685 (traverseproc)gc_traverse, /* tp_traverse */
686 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000687 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000688 0, /* tp_weaklistoffset */
689 (getiterfunc)proxy_iter, /* tp_iter */
690 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000692};
693
694
695PyTypeObject
696_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000697 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000698 "weakcallableproxy",
699 sizeof(PyWeakReference),
700 0,
701 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000702 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000703 0, /* tp_print */
704 0, /* tp_getattr */
705 0, /* tp_setattr */
706 0, /* tp_reserved */
707 (unaryfunc)proxy_repr, /* tp_repr */
708 &proxy_as_number, /* tp_as_number */
709 &proxy_as_sequence, /* tp_as_sequence */
710 &proxy_as_mapping, /* tp_as_mapping */
711 0, /* tp_hash */
712 proxy_call, /* tp_call */
713 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000714 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000715 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000716 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000717 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000718 0, /* tp_doc */
719 (traverseproc)gc_traverse, /* tp_traverse */
720 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000721 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000722 0, /* tp_weaklistoffset */
723 (getiterfunc)proxy_iter, /* tp_iter */
724 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000725};
726
727
Fred Drake8844d522001-10-05 21:52:26 +0000728
729PyObject *
730PyWeakref_NewRef(PyObject *ob, PyObject *callback)
731{
732 PyWeakReference *result = NULL;
733 PyWeakReference **list;
734 PyWeakReference *ref, *proxy;
735
Christian Heimes90aa7642007-12-19 02:45:37 +0000736 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000737 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000739 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000740 return NULL;
741 }
742 list = GET_WEAKREFS_LISTPTR(ob);
743 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000744 if (callback == Py_None)
745 callback = NULL;
746 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000747 /* return existing weak reference if it exists */
748 result = ref;
749 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000750 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000751 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000752 /* Note: new_weakref() can trigger cyclic GC, so the weakref
753 list on ob can be mutated. This means that the ref and
754 proxy pointers we got back earlier may have been collected,
755 so we need to compute these values again before we use
756 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000757 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000758 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000759 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000760 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000761 if (ref == NULL)
762 insert_head(result, list);
763 else {
764 /* Someone else added a ref without a callback
765 during GC. Return that one instead of this one
766 to avoid violating the invariants of the list
767 of weakrefs for ob. */
768 Py_DECREF(result);
769 Py_INCREF(ref);
770 result = ref;
771 }
Fred Drake8844d522001-10-05 21:52:26 +0000772 }
773 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000774 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000775
Fred Drakebc875f52004-02-04 23:14:14 +0000776 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000777 if (prev == NULL)
778 insert_head(result, list);
779 else
780 insert_after(result, prev);
781 }
Fred Drake8844d522001-10-05 21:52:26 +0000782 }
783 }
784 return (PyObject *) result;
785}
786
787
788PyObject *
789PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
790{
791 PyWeakReference *result = NULL;
792 PyWeakReference **list;
793 PyWeakReference *ref, *proxy;
794
Christian Heimes90aa7642007-12-19 02:45:37 +0000795 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000796 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000798 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000799 return NULL;
800 }
801 list = GET_WEAKREFS_LISTPTR(ob);
802 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000803 if (callback == Py_None)
804 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000805 if (callback == NULL)
806 /* attempt to return an existing weak reference if it exists */
807 result = proxy;
808 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000809 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000810 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000811 /* Note: new_weakref() can trigger cyclic GC, so the weakref
812 list on ob can be mutated. This means that the ref and
813 proxy pointers we got back earlier may have been collected,
814 so we need to compute these values again before we use
815 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000816 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000817 if (result != NULL) {
818 PyWeakReference *prev;
819
820 if (PyCallable_Check(ob))
Christian Heimes90aa7642007-12-19 02:45:37 +0000821 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000822 else
Christian Heimes90aa7642007-12-19 02:45:37 +0000823 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000824 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000825 if (callback == NULL) {
826 if (proxy != NULL) {
827 /* Someone else added a proxy without a callback
828 during GC. Return that one instead of this one
829 to avoid violating the invariants of the list
830 of weakrefs for ob. */
831 Py_DECREF(result);
832 Py_INCREF(result = proxy);
833 goto skip_insert;
834 }
Fred Drake8844d522001-10-05 21:52:26 +0000835 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000836 }
Fred Drake8844d522001-10-05 21:52:26 +0000837 else
838 prev = (proxy == NULL) ? ref : proxy;
839
840 if (prev == NULL)
841 insert_head(result, list);
842 else
843 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000844 skip_insert:
845 ;
Fred Drake8844d522001-10-05 21:52:26 +0000846 }
847 }
848 return (PyObject *) result;
849}
850
851
852PyObject *
853PyWeakref_GetObject(PyObject *ref)
854{
855 if (ref == NULL || !PyWeakref_Check(ref)) {
856 PyErr_BadInternalCall();
857 return NULL;
858 }
859 return PyWeakref_GET_OBJECT(ref);
860}
861
Tim Petersead8b7a2004-10-30 23:09:22 +0000862/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
863 * handle_weakrefs().
864 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000865static void
866handle_callback(PyWeakReference *ref, PyObject *callback)
867{
Thomas Wouters477c8d52006-05-27 19:21:47 +0000868 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000869
870 if (cbresult == NULL)
871 PyErr_WriteUnraisable(callback);
872 else
873 Py_DECREF(cbresult);
874}
875
876/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000877 *
878 * This iterates through the weak references for 'object' and calls callbacks
879 * for those references which have one. It returns when all callbacks have
880 * been attempted.
881 */
882void
883PyObject_ClearWeakRefs(PyObject *object)
884{
885 PyWeakReference **list;
886
887 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000888 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000889 || object->ob_refcnt != 0) {
890 PyErr_BadInternalCall();
891 return;
892 }
893 list = GET_WEAKREFS_LISTPTR(object);
894 /* Remove the callback-less basic and proxy references */
895 if (*list != NULL && (*list)->wr_callback == NULL) {
896 clear_weakref(*list);
897 if (*list != NULL && (*list)->wr_callback == NULL)
898 clear_weakref(*list);
899 }
900 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000901 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000902 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000903 int restore_error = PyErr_Occurred() ? 1 : 0;
904 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000905
Fred Drakeef8ebd12001-12-10 23:44:54 +0000906 if (restore_error)
907 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) {
925 if (restore_error)
926 PyErr_Fetch(&err_type, &err_value, &err_tb);
927 return;
928 }
Fred Drake8844d522001-10-05 21:52:26 +0000929
930 for (i = 0; i < count; ++i) {
931 PyWeakReference *next = current->wr_next;
932
Benjamin Petersona38d1562008-06-16 20:47:12 +0000933 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000934 {
935 Py_INCREF(current);
936 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
937 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
938 }
939 else {
940 Py_DECREF(current->wr_callback);
941 }
Fred Drake8844d522001-10-05 21:52:26 +0000942 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000943 clear_weakref(current);
944 current = next;
945 }
946 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000947 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000948
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000949 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000950 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000951 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
952 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000953 }
Fred Drake8844d522001-10-05 21:52:26 +0000954 }
955 Py_DECREF(tuple);
956 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000957 if (restore_error)
958 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000959 }
960}