blob: 1aee5a55302f74f46247c101826f08ae1e72c6ba [file] [log] [blame]
Fred Drake8844d522001-10-05 21:52:26 +00001#include "Python.h"
2#include "structmember.h"
3
4
5#define GET_WEAKREFS_LISTPTR(o) \
6 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
7
Fred Drake8844d522001-10-05 21:52:26 +00008
Neal Norwitzc5e060d2006-08-02 06:14:22 +00009Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +000010_PyWeakref_GetWeakrefCount(PyWeakReference *head)
11{
Neal Norwitzc5e060d2006-08-02 06:14:22 +000012 Py_ssize_t count = 0;
Fred Drake8844d522001-10-05 21:52:26 +000013
14 while (head != NULL) {
15 ++count;
16 head = head->wr_next;
17 }
18 return count;
19}
20
21
Fred Drake0a4dd392004-07-02 18:57:45 +000022static void
23init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
24{
25 self->hash = -1;
26 self->wr_object = ob;
27 Py_XINCREF(callback);
28 self->wr_callback = callback;
29}
30
Fred Drake8844d522001-10-05 21:52:26 +000031static PyWeakReference *
Neil Schemenauer38a89162002-03-27 15:18:21 +000032new_weakref(PyObject *ob, PyObject *callback)
Fred Drake8844d522001-10-05 21:52:26 +000033{
34 PyWeakReference *result;
35
Neil Schemenauer38a89162002-03-27 15:18:21 +000036 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
37 if (result) {
Fred Drake0a4dd392004-07-02 18:57:45 +000038 init_weakref(result, ob, callback);
Neil Schemenauer38a89162002-03-27 15:18:21 +000039 PyObject_GC_Track(result);
40 }
Fred Drake8844d522001-10-05 21:52:26 +000041 return result;
42}
43
44
45/* This function clears the passed-in reference and removes it from the
46 * list of weak references for the referent. This is the only code that
47 * removes an item from the doubly-linked list of weak references for an
48 * object; it is also responsible for clearing the callback slot.
49 */
50static void
51clear_weakref(PyWeakReference *self)
52{
53 PyObject *callback = self->wr_callback;
54
55 if (PyWeakref_GET_OBJECT(self) != Py_None) {
56 PyWeakReference **list = GET_WEAKREFS_LISTPTR(
57 PyWeakref_GET_OBJECT(self));
58
59 if (*list == self)
Brett Cannonf5bee302007-01-23 23:21:22 +000060 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
61 then the weakref list itself (and thus the value of *list) will
62 end up being set to NULL. */
Fred Drake8844d522001-10-05 21:52:26 +000063 *list = self->wr_next;
64 self->wr_object = Py_None;
Fred Drake8844d522001-10-05 21:52:26 +000065 if (self->wr_prev != NULL)
66 self->wr_prev->wr_next = self->wr_next;
67 if (self->wr_next != NULL)
68 self->wr_next->wr_prev = self->wr_prev;
69 self->wr_prev = NULL;
70 self->wr_next = NULL;
Tim Peters403a2032003-11-20 21:21:46 +000071 }
72 if (callback != NULL) {
73 Py_DECREF(callback);
74 self->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +000075 }
76}
77
Tim Peters403a2032003-11-20 21:21:46 +000078/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
79 * the callback intact and uncalled. It must be possible to call self's
80 * tp_dealloc() after calling this, so self has to be left in a sane enough
81 * state for that to work. We expect tp_dealloc to decref the callback
82 * then. The reason for not letting clear_weakref() decref the callback
83 * right now is that if the callback goes away, that may in turn trigger
84 * another callback (if a weak reference to the callback exists) -- running
85 * arbitrary Python code in the middle of gc is a disaster. The convolution
86 * here allows gc to delay triggering such callbacks until the world is in
87 * a sane state again.
88 */
89void
90_PyWeakref_ClearRef(PyWeakReference *self)
91{
92 PyObject *callback;
93
94 assert(self != NULL);
95 assert(PyWeakref_Check(self));
96 /* Preserve and restore the callback around clear_weakref. */
97 callback = self->wr_callback;
98 self->wr_callback = NULL;
99 clear_weakref(self);
100 self->wr_callback = callback;
101}
Fred Drake8844d522001-10-05 21:52:26 +0000102
103static void
Fred Drake0a4dd392004-07-02 18:57:45 +0000104weakref_dealloc(PyObject *self)
Fred Drake8844d522001-10-05 21:52:26 +0000105{
Fred Drake0a4dd392004-07-02 18:57:45 +0000106 PyObject_GC_UnTrack(self);
107 clear_weakref((PyWeakReference *) self);
Christian Heimese93237d2007-12-19 02:37:44 +0000108 Py_TYPE(self)->tp_free(self);
Fred Drake8844d522001-10-05 21:52:26 +0000109}
110
111
112static int
113gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
114{
Thomas Woutersc6e55062006-04-15 21:47:09 +0000115 Py_VISIT(self->wr_callback);
Fred Drake8844d522001-10-05 21:52:26 +0000116 return 0;
117}
118
119
120static int
121gc_clear(PyWeakReference *self)
122{
123 clear_weakref(self);
124 return 0;
125}
126
127
128static PyObject *
129weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
130{
Martin v. Löwis15e62742006-02-27 16:46:16 +0000131 static char *kwlist[] = {NULL};
Fred Drake8844d522001-10-05 21:52:26 +0000132
Martin v. Löwis15e62742006-02-27 16:46:16 +0000133 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
Fred Drake8844d522001-10-05 21:52:26 +0000134 PyObject *object = PyWeakref_GET_OBJECT(self);
135 Py_INCREF(object);
136 return (object);
137 }
138 return NULL;
139}
140
141
142static long
143weakref_hash(PyWeakReference *self)
144{
145 if (self->hash != -1)
146 return self->hash;
147 if (PyWeakref_GET_OBJECT(self) == Py_None) {
148 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
149 return -1;
150 }
151 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
152 return self->hash;
153}
Tim Peters403a2032003-11-20 21:21:46 +0000154
Fred Drake8844d522001-10-05 21:52:26 +0000155
156static PyObject *
157weakref_repr(PyWeakReference *self)
158{
159 char buffer[256];
160 if (PyWeakref_GET_OBJECT(self) == Py_None) {
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000161 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
Fred Drake8844d522001-10-05 21:52:26 +0000162 }
163 else {
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000164 char *name = NULL;
165 PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
166 "__name__");
167 if (nameobj == NULL)
168 PyErr_Clear();
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000169 else if (PyString_Check(nameobj))
170 name = PyString_AS_STRING(nameobj);
Barry Warsawd5867562001-11-28 21:01:56 +0000171 PyOS_snprintf(buffer, sizeof(buffer),
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000172 name ? "<weakref at %p; to '%.50s' at %p (%s)>"
173 : "<weakref at %p; to '%.50s' at %p>",
174 self,
Christian Heimese93237d2007-12-19 02:37:44 +0000175 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000176 PyWeakref_GET_OBJECT(self),
177 name);
178 Py_XDECREF(nameobj);
Fred Drake8844d522001-10-05 21:52:26 +0000179 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000180 return PyString_FromString(buffer);
Fred Drake8844d522001-10-05 21:52:26 +0000181}
182
183/* Weak references only support equality, not ordering. Two weak references
184 are equal if the underlying objects are equal. If the underlying object has
185 gone away, they are equal if they are identical. */
186
187static PyObject *
188weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
189{
190 if (op != Py_EQ || self->ob_type != other->ob_type) {
191 Py_INCREF(Py_NotImplemented);
192 return Py_NotImplemented;
193 }
194 if (PyWeakref_GET_OBJECT(self) == Py_None
195 || PyWeakref_GET_OBJECT(other) == Py_None) {
196 PyObject *res = self==other ? Py_True : Py_False;
197 Py_INCREF(res);
198 return res;
199 }
200 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
201 PyWeakref_GET_OBJECT(other), op);
202}
203
Fred Drake0a4dd392004-07-02 18:57:45 +0000204/* Given the head of an object's list of weak references, extract the
205 * two callback-less refs (ref and proxy). Used to determine if the
206 * shared references exist and to determine the back link for newly
207 * inserted references.
208 */
209static void
210get_basic_refs(PyWeakReference *head,
211 PyWeakReference **refp, PyWeakReference **proxyp)
212{
213 *refp = NULL;
214 *proxyp = NULL;
215
216 if (head != NULL && head->wr_callback == NULL) {
217 /* We need to be careful that the "basic refs" aren't
218 subclasses of the main types. That complicates this a
219 little. */
220 if (PyWeakref_CheckRefExact(head)) {
221 *refp = head;
222 head = head->wr_next;
223 }
224 if (head != NULL
225 && head->wr_callback == NULL
226 && PyWeakref_CheckProxy(head)) {
227 *proxyp = head;
228 /* head = head->wr_next; */
229 }
230 }
231}
232
233/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
234static void
235insert_after(PyWeakReference *newref, PyWeakReference *prev)
236{
237 newref->wr_prev = prev;
238 newref->wr_next = prev->wr_next;
239 if (prev->wr_next != NULL)
240 prev->wr_next->wr_prev = newref;
241 prev->wr_next = newref;
242}
243
244/* Insert 'newref' at the head of the list; 'list' points to the variable
245 * that stores the head.
246 */
247static void
248insert_head(PyWeakReference *newref, PyWeakReference **list)
249{
250 PyWeakReference *next = *list;
251
252 newref->wr_prev = NULL;
253 newref->wr_next = next;
254 if (next != NULL)
255 next->wr_prev = newref;
256 *list = newref;
257}
258
259static int
260parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
261 PyObject **obp, PyObject **callbackp)
262{
263 /* XXX Should check that kwargs == NULL or is empty. */
264 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
265}
266
267static PyObject *
268weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
269{
270 PyWeakReference *self = NULL;
271 PyObject *ob, *callback = NULL;
272
273 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
274 PyWeakReference *ref, *proxy;
275 PyWeakReference **list;
276
Christian Heimese93237d2007-12-19 02:37:44 +0000277 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000278 PyErr_Format(PyExc_TypeError,
279 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000280 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000281 return NULL;
282 }
283 if (callback == Py_None)
284 callback = NULL;
285 list = GET_WEAKREFS_LISTPTR(ob);
286 get_basic_refs(*list, &ref, &proxy);
287 if (callback == NULL && type == &_PyWeakref_RefType) {
288 if (ref != NULL) {
289 /* We can re-use an existing reference. */
290 Py_INCREF(ref);
291 return (PyObject *)ref;
292 }
293 }
294 /* We have to create a new reference. */
295 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
296 list on ob can be mutated. This means that the ref and
297 proxy pointers we got back earlier may have been collected,
298 so we need to compute these values again before we use
299 them. */
300 self = (PyWeakReference *) (type->tp_alloc(type, 0));
301 if (self != NULL) {
302 init_weakref(self, ob, callback);
303 if (callback == NULL && type == &_PyWeakref_RefType) {
304 insert_head(self, list);
305 }
306 else {
307 PyWeakReference *prev;
308
309 get_basic_refs(*list, &ref, &proxy);
310 prev = (proxy == NULL) ? ref : proxy;
311 if (prev == NULL)
312 insert_head(self, list);
313 else
314 insert_after(self, prev);
315 }
316 }
317 }
318 return (PyObject *)self;
319}
320
321static int
322weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
323{
324 PyObject *tmp;
325
326 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
327 return 0;
328 else
329 return 1;
330}
331
Fred Drake8844d522001-10-05 21:52:26 +0000332
333PyTypeObject
334_PyWeakref_RefType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000335 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000336 "weakref",
337 sizeof(PyWeakReference),
338 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000339 weakref_dealloc, /*tp_dealloc*/
Fred Drake8844d522001-10-05 21:52:26 +0000340 0, /*tp_print*/
341 0, /*tp_getattr*/
342 0, /*tp_setattr*/
343 0, /*tp_compare*/
344 (reprfunc)weakref_repr, /*tp_repr*/
345 0, /*tp_as_number*/
346 0, /*tp_as_sequence*/
347 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000348 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000349 (ternaryfunc)weakref_call, /*tp_call*/
350 0, /*tp_str*/
351 0, /*tp_getattro*/
352 0, /*tp_setattro*/
353 0, /*tp_as_buffer*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000354 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
355 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000356 0, /*tp_doc*/
357 (traverseproc)gc_traverse, /*tp_traverse*/
358 (inquiry)gc_clear, /*tp_clear*/
359 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000360 0, /*tp_weaklistoffset*/
361 0, /*tp_iter*/
362 0, /*tp_iternext*/
363 0, /*tp_methods*/
364 0, /*tp_members*/
365 0, /*tp_getset*/
366 0, /*tp_base*/
367 0, /*tp_dict*/
368 0, /*tp_descr_get*/
369 0, /*tp_descr_set*/
370 0, /*tp_dictoffset*/
Georg Brandl347b3002006-03-30 11:57:00 +0000371 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000372 PyType_GenericAlloc, /*tp_alloc*/
373 weakref___new__, /*tp_new*/
374 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000375};
376
377
378static int
379proxy_checkref(PyWeakReference *proxy)
380{
381 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
382 PyErr_SetString(PyExc_ReferenceError,
383 "weakly-referenced object no longer exists");
384 return 0;
385 }
386 return 1;
387}
388
389
Fred Drake73006d02001-10-18 18:04:18 +0000390/* If a parameter is a proxy, check that it is still "live" and wrap it,
391 * replacing the original value with the raw object. Raises ReferenceError
392 * if the param is a dead proxy.
393 */
394#define UNWRAP(o) \
395 if (PyWeakref_CheckProxy(o)) { \
396 if (!proxy_checkref((PyWeakReference *)o)) \
397 return NULL; \
398 o = PyWeakref_GET_OBJECT(o); \
399 }
400
Fred Drake2a908f62001-12-19 16:44:30 +0000401#define UNWRAP_I(o) \
402 if (PyWeakref_CheckProxy(o)) { \
403 if (!proxy_checkref((PyWeakReference *)o)) \
404 return -1; \
405 o = PyWeakref_GET_OBJECT(o); \
406 }
407
Fred Drake8844d522001-10-05 21:52:26 +0000408#define WRAP_UNARY(method, generic) \
409 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000410 method(PyObject *proxy) { \
411 UNWRAP(proxy); \
412 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000413 }
414
415#define WRAP_BINARY(method, generic) \
416 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000417 method(PyObject *x, PyObject *y) { \
418 UNWRAP(x); \
419 UNWRAP(y); \
420 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000421 }
422
Fred Drake31f4d1f2001-10-18 19:21:46 +0000423/* Note that the third arg needs to be checked for NULL since the tp_call
424 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000425 */
Fred Drake8844d522001-10-05 21:52:26 +0000426#define WRAP_TERNARY(method, generic) \
427 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000428 method(PyObject *proxy, PyObject *v, PyObject *w) { \
429 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000430 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000431 if (w != NULL) \
432 UNWRAP(w); \
433 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000434 }
435
436
437/* direct slots */
438
439WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
440WRAP_UNARY(proxy_str, PyObject_Str)
441WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
442
Fred Drake8844d522001-10-05 21:52:26 +0000443static PyObject *
444proxy_repr(PyWeakReference *proxy)
445{
446 char buf[160];
Barry Warsawd5867562001-11-28 21:01:56 +0000447 PyOS_snprintf(buf, sizeof(buf),
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000448 "<weakproxy at %p to %.100s at %p>", proxy,
Christian Heimese93237d2007-12-19 02:37:44 +0000449 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
Barry Warsawd5867562001-11-28 21:01:56 +0000450 PyWeakref_GET_OBJECT(proxy));
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000451 return PyString_FromString(buf);
Fred Drake8844d522001-10-05 21:52:26 +0000452}
453
454
455static int
456proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
457{
458 if (!proxy_checkref(proxy))
459 return -1;
460 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
461}
462
463static int
Fred Drake2a908f62001-12-19 16:44:30 +0000464proxy_compare(PyObject *proxy, PyObject *v)
Fred Drake8844d522001-10-05 21:52:26 +0000465{
Fred Drake2a908f62001-12-19 16:44:30 +0000466 UNWRAP_I(proxy);
467 UNWRAP_I(v);
468 return PyObject_Compare(proxy, v);
Fred Drake8844d522001-10-05 21:52:26 +0000469}
470
471/* number slots */
472WRAP_BINARY(proxy_add, PyNumber_Add)
473WRAP_BINARY(proxy_sub, PyNumber_Subtract)
474WRAP_BINARY(proxy_mul, PyNumber_Multiply)
475WRAP_BINARY(proxy_div, PyNumber_Divide)
Georg Brandl88659b02008-05-20 08:40:43 +0000476WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
477WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000478WRAP_BINARY(proxy_mod, PyNumber_Remainder)
479WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
480WRAP_TERNARY(proxy_pow, PyNumber_Power)
481WRAP_UNARY(proxy_neg, PyNumber_Negative)
482WRAP_UNARY(proxy_pos, PyNumber_Positive)
483WRAP_UNARY(proxy_abs, PyNumber_Absolute)
484WRAP_UNARY(proxy_invert, PyNumber_Invert)
485WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
486WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
487WRAP_BINARY(proxy_and, PyNumber_And)
488WRAP_BINARY(proxy_xor, PyNumber_Xor)
489WRAP_BINARY(proxy_or, PyNumber_Or)
490WRAP_UNARY(proxy_int, PyNumber_Int)
491WRAP_UNARY(proxy_long, PyNumber_Long)
492WRAP_UNARY(proxy_float, PyNumber_Float)
493WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
494WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
495WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
496WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
Georg Brandl88659b02008-05-20 08:40:43 +0000497WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
498WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000499WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
500WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
501WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
502WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
503WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
504WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
505WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandl88659b02008-05-20 08:40:43 +0000506WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000507
Tim Peters403a2032003-11-20 21:21:46 +0000508static int
Fred Drake8844d522001-10-05 21:52:26 +0000509proxy_nonzero(PyWeakReference *proxy)
510{
511 PyObject *o = PyWeakref_GET_OBJECT(proxy);
512 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000513 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000514 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000515}
516
Fred Drake0a4dd392004-07-02 18:57:45 +0000517static void
518proxy_dealloc(PyWeakReference *self)
519{
520 if (self->wr_callback != NULL)
521 PyObject_GC_UnTrack((PyObject *)self);
522 clear_weakref(self);
523 PyObject_GC_Del(self);
524}
525
Fred Drake8844d522001-10-05 21:52:26 +0000526/* sequence slots */
527
528static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000529proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
Fred Drake8844d522001-10-05 21:52:26 +0000530{
531 if (!proxy_checkref(proxy))
532 return NULL;
533 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
534}
535
536static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000537proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
Fred Drake8844d522001-10-05 21:52:26 +0000538{
539 if (!proxy_checkref(proxy))
540 return -1;
541 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
542}
543
544static int
545proxy_contains(PyWeakReference *proxy, PyObject *value)
546{
547 if (!proxy_checkref(proxy))
548 return -1;
549 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
550}
551
552
553/* mapping slots */
554
Martin v. Löwis18e16552006-02-15 17:27:45 +0000555static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000556proxy_length(PyWeakReference *proxy)
557{
558 if (!proxy_checkref(proxy))
559 return -1;
560 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
561}
562
563WRAP_BINARY(proxy_getitem, PyObject_GetItem)
564
565static int
566proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
567{
568 if (!proxy_checkref(proxy))
569 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000570
571 if (value == NULL)
572 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
573 else
574 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000575}
576
Fred Drakef16c3dc2002-08-09 18:34:16 +0000577/* iterator slots */
578
579static PyObject *
580proxy_iter(PyWeakReference *proxy)
581{
582 if (!proxy_checkref(proxy))
583 return NULL;
584 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
585}
586
587static PyObject *
588proxy_iternext(PyWeakReference *proxy)
589{
590 if (!proxy_checkref(proxy))
591 return NULL;
592 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
593}
594
Fred Drake8844d522001-10-05 21:52:26 +0000595
596static PyNumberMethods proxy_as_number = {
Georg Brandl347b3002006-03-30 11:57:00 +0000597 proxy_add, /*nb_add*/
598 proxy_sub, /*nb_subtract*/
599 proxy_mul, /*nb_multiply*/
600 proxy_div, /*nb_divide*/
601 proxy_mod, /*nb_remainder*/
602 proxy_divmod, /*nb_divmod*/
603 proxy_pow, /*nb_power*/
604 proxy_neg, /*nb_negative*/
605 proxy_pos, /*nb_positive*/
606 proxy_abs, /*nb_absolute*/
607 (inquiry)proxy_nonzero, /*nb_nonzero*/
608 proxy_invert, /*nb_invert*/
609 proxy_lshift, /*nb_lshift*/
610 proxy_rshift, /*nb_rshift*/
611 proxy_and, /*nb_and*/
612 proxy_xor, /*nb_xor*/
613 proxy_or, /*nb_or*/
614 0, /*nb_coerce*/
615 proxy_int, /*nb_int*/
616 proxy_long, /*nb_long*/
617 proxy_float, /*nb_float*/
618 0, /*nb_oct*/
619 0, /*nb_hex*/
620 proxy_iadd, /*nb_inplace_add*/
621 proxy_isub, /*nb_inplace_subtract*/
622 proxy_imul, /*nb_inplace_multiply*/
623 proxy_idiv, /*nb_inplace_divide*/
624 proxy_imod, /*nb_inplace_remainder*/
625 proxy_ipow, /*nb_inplace_power*/
626 proxy_ilshift, /*nb_inplace_lshift*/
627 proxy_irshift, /*nb_inplace_rshift*/
628 proxy_iand, /*nb_inplace_and*/
629 proxy_ixor, /*nb_inplace_xor*/
630 proxy_ior, /*nb_inplace_or*/
Georg Brandl88659b02008-05-20 08:40:43 +0000631 proxy_floor_div, /*nb_floor_divide*/
632 proxy_true_div, /*nb_true_divide*/
633 proxy_ifloor_div, /*nb_inplace_floor_divide*/
634 proxy_itrue_div, /*nb_inplace_true_divide*/
635 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000636};
637
638static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000639 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000640 0, /*sq_concat*/
641 0, /*sq_repeat*/
642 0, /*sq_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000643 (ssizessizeargfunc)proxy_slice, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000644 0, /*sq_ass_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000645 (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000646 (objobjproc)proxy_contains, /* sq_contains */
647};
648
649static PyMappingMethods proxy_as_mapping = {
Georg Brandl347b3002006-03-30 11:57:00 +0000650 (lenfunc)proxy_length, /*mp_length*/
651 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000652 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
653};
654
655
656PyTypeObject
657_PyWeakref_ProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000658 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000659 "weakproxy",
660 sizeof(PyWeakReference),
661 0,
662 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000663 (destructor)proxy_dealloc, /* tp_dealloc */
Fred Drakefe89cc12003-07-14 21:46:23 +0000664 0, /* tp_print */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000665 0, /* tp_getattr */
666 0, /* tp_setattr */
667 proxy_compare, /* tp_compare */
Georg Brandl347b3002006-03-30 11:57:00 +0000668 (reprfunc)proxy_repr, /* tp_repr */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000669 &proxy_as_number, /* tp_as_number */
670 &proxy_as_sequence, /* tp_as_sequence */
671 &proxy_as_mapping, /* tp_as_mapping */
672 0, /* tp_hash */
Georg Brandl347b3002006-03-30 11:57:00 +0000673 0, /* tp_call */
674 proxy_str, /* tp_str */
675 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000676 (setattrofunc)proxy_setattr, /* tp_setattro */
677 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000678 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000679 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
680 0, /* tp_doc */
681 (traverseproc)gc_traverse, /* tp_traverse */
682 (inquiry)gc_clear, /* tp_clear */
683 0, /* tp_richcompare */
684 0, /* tp_weaklistoffset */
685 (getiterfunc)proxy_iter, /* tp_iter */
686 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000687};
688
689
690PyTypeObject
691_PyWeakref_CallableProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000692 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000693 "weakcallableproxy",
694 sizeof(PyWeakReference),
695 0,
696 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000697 (destructor)proxy_dealloc, /* tp_dealloc */
Fred Drakefe89cc12003-07-14 21:46:23 +0000698 0, /* tp_print */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000699 0, /* tp_getattr */
700 0, /* tp_setattr */
701 proxy_compare, /* tp_compare */
702 (unaryfunc)proxy_repr, /* tp_repr */
703 &proxy_as_number, /* tp_as_number */
704 &proxy_as_sequence, /* tp_as_sequence */
705 &proxy_as_mapping, /* tp_as_mapping */
706 0, /* tp_hash */
Georg Brandl347b3002006-03-30 11:57:00 +0000707 proxy_call, /* tp_call */
708 proxy_str, /* tp_str */
709 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000710 (setattrofunc)proxy_setattr, /* tp_setattro */
711 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000712 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000713 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
714 0, /* tp_doc */
715 (traverseproc)gc_traverse, /* tp_traverse */
716 (inquiry)gc_clear, /* tp_clear */
717 0, /* tp_richcompare */
718 0, /* tp_weaklistoffset */
719 (getiterfunc)proxy_iter, /* tp_iter */
720 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000721};
722
723
Fred Drake8844d522001-10-05 21:52:26 +0000724
725PyObject *
726PyWeakref_NewRef(PyObject *ob, PyObject *callback)
727{
728 PyWeakReference *result = NULL;
729 PyWeakReference **list;
730 PyWeakReference *ref, *proxy;
731
Christian Heimese93237d2007-12-19 02:37:44 +0000732 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000733 PyErr_Format(PyExc_TypeError,
Jeremy Hylton996fad32001-10-22 16:31:40 +0000734 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000735 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000736 return NULL;
737 }
738 list = GET_WEAKREFS_LISTPTR(ob);
739 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000740 if (callback == Py_None)
741 callback = NULL;
742 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000743 /* return existing weak reference if it exists */
744 result = ref;
745 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000746 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000747 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000748 /* Note: new_weakref() can trigger cyclic GC, so the weakref
749 list on ob can be mutated. This means that the ref and
750 proxy pointers we got back earlier may have been collected,
751 so we need to compute these values again before we use
752 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000753 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000754 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000755 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000756 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000757 if (ref == NULL)
758 insert_head(result, list);
759 else {
760 /* Someone else added a ref without a callback
761 during GC. Return that one instead of this one
762 to avoid violating the invariants of the list
763 of weakrefs for ob. */
764 Py_DECREF(result);
765 Py_INCREF(ref);
766 result = ref;
767 }
Fred Drake8844d522001-10-05 21:52:26 +0000768 }
769 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000770 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000771
Fred Drakebc875f52004-02-04 23:14:14 +0000772 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000773 if (prev == NULL)
774 insert_head(result, list);
775 else
776 insert_after(result, prev);
777 }
Fred Drake8844d522001-10-05 21:52:26 +0000778 }
779 }
780 return (PyObject *) result;
781}
782
783
784PyObject *
785PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
786{
787 PyWeakReference *result = NULL;
788 PyWeakReference **list;
789 PyWeakReference *ref, *proxy;
790
Christian Heimese93237d2007-12-19 02:37:44 +0000791 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000792 PyErr_Format(PyExc_TypeError,
Jeremy Hylton996fad32001-10-22 16:31:40 +0000793 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000794 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000795 return NULL;
796 }
797 list = GET_WEAKREFS_LISTPTR(ob);
798 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000799 if (callback == Py_None)
800 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000801 if (callback == NULL)
802 /* attempt to return an existing weak reference if it exists */
803 result = proxy;
804 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000805 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000806 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000807 /* Note: new_weakref() can trigger cyclic GC, so the weakref
808 list on ob can be mutated. This means that the ref and
809 proxy pointers we got back earlier may have been collected,
810 so we need to compute these values again before we use
811 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000812 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000813 if (result != NULL) {
814 PyWeakReference *prev;
815
816 if (PyCallable_Check(ob))
Christian Heimese93237d2007-12-19 02:37:44 +0000817 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000818 else
Christian Heimese93237d2007-12-19 02:37:44 +0000819 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000820 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000821 if (callback == NULL) {
822 if (proxy != NULL) {
823 /* Someone else added a proxy without a callback
824 during GC. Return that one instead of this one
825 to avoid violating the invariants of the list
826 of weakrefs for ob. */
827 Py_DECREF(result);
828 Py_INCREF(result = proxy);
829 goto skip_insert;
830 }
Fred Drake8844d522001-10-05 21:52:26 +0000831 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000832 }
Fred Drake8844d522001-10-05 21:52:26 +0000833 else
834 prev = (proxy == NULL) ? ref : proxy;
835
836 if (prev == NULL)
837 insert_head(result, list);
838 else
839 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000840 skip_insert:
841 ;
Fred Drake8844d522001-10-05 21:52:26 +0000842 }
843 }
844 return (PyObject *) result;
845}
846
847
848PyObject *
849PyWeakref_GetObject(PyObject *ref)
850{
851 if (ref == NULL || !PyWeakref_Check(ref)) {
852 PyErr_BadInternalCall();
853 return NULL;
854 }
855 return PyWeakref_GET_OBJECT(ref);
856}
857
Tim Petersead8b7a2004-10-30 23:09:22 +0000858/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
859 * handle_weakrefs().
860 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000861static void
862handle_callback(PyWeakReference *ref, PyObject *callback)
863{
Georg Brandl684fd0c2006-05-25 19:15:31 +0000864 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000865
866 if (cbresult == NULL)
867 PyErr_WriteUnraisable(callback);
868 else
869 Py_DECREF(cbresult);
870}
871
872/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000873 *
874 * This iterates through the weak references for 'object' and calls callbacks
875 * for those references which have one. It returns when all callbacks have
876 * been attempted.
877 */
878void
879PyObject_ClearWeakRefs(PyObject *object)
880{
881 PyWeakReference **list;
882
883 if (object == NULL
Christian Heimese93237d2007-12-19 02:37:44 +0000884 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000885 || object->ob_refcnt != 0) {
886 PyErr_BadInternalCall();
887 return;
888 }
889 list = GET_WEAKREFS_LISTPTR(object);
890 /* Remove the callback-less basic and proxy references */
891 if (*list != NULL && (*list)->wr_callback == NULL) {
892 clear_weakref(*list);
893 if (*list != NULL && (*list)->wr_callback == NULL)
894 clear_weakref(*list);
895 }
896 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000897 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000898 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000899 int restore_error = PyErr_Occurred() ? 1 : 0;
900 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000901
Fred Drakeef8ebd12001-12-10 23:44:54 +0000902 if (restore_error)
903 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000904 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000905 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000906
Fred Drakeef8ebd12001-12-10 23:44:54 +0000907 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000908 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000909 if (callback != NULL) {
910 handle_callback(current, callback);
911 Py_DECREF(callback);
912 }
Fred Drake8844d522001-10-05 21:52:26 +0000913 }
914 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000915 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000916 Py_ssize_t i = 0;
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000917
918 tuple = PyTuple_New(count * 2);
919 if (tuple == NULL) {
920 if (restore_error)
921 PyErr_Fetch(&err_type, &err_value, &err_tb);
922 return;
923 }
Fred Drake8844d522001-10-05 21:52:26 +0000924
925 for (i = 0; i < count; ++i) {
926 PyWeakReference *next = current->wr_next;
927
928 Py_INCREF(current);
929 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
930 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
931 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000932 clear_weakref(current);
933 current = next;
934 }
935 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000936 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000937
Fred Drake0a4dd392004-07-02 18:57:45 +0000938 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000939 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
940 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000941 }
Fred Drake8844d522001-10-05 21:52:26 +0000942 }
943 Py_DECREF(tuple);
944 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000945 if (restore_error)
946 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000947 }
948}