blob: 58fe09fa3b51b025a309c09ddeeb45b854292ab6 [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;
Pablo Galindo526ef852019-10-08 21:38:11 +0100148 PyObject* obj = PyWeakref_GET_OBJECT(self);
149 if (obj == Py_None) {
Fred Drake8844d522001-10-05 21:52:26 +0000150 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
151 return -1;
152 }
Pablo Galindo526ef852019-10-08 21:38:11 +0100153 Py_INCREF(obj);
154 self->hash = PyObject_Hash(obj);
155 Py_DECREF(obj);
Fred Drake8844d522001-10-05 21:52:26 +0000156 return self->hash;
157}
Tim Peters403a2032003-11-20 21:21:46 +0000158
Fred Drake8844d522001-10-05 21:52:26 +0000159
160static PyObject *
161weakref_repr(PyWeakReference *self)
162{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100163 PyObject *name, *repr;
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200164 _Py_IDENTIFIER(__name__);
Pablo Galindo526ef852019-10-08 21:38:11 +0100165 PyObject* obj = PyWeakref_GET_OBJECT(self);
Victor Stinner499dfcf2011-03-21 13:26:24 +0100166
Pablo Galindo526ef852019-10-08 21:38:11 +0100167 if (obj == Py_None) {
Victor Stinner499dfcf2011-03-21 13:26:24 +0100168 return PyUnicode_FromFormat("<weakref at %p; dead>", self);
Pablo Galindo526ef852019-10-08 21:38:11 +0100169 }
Victor Stinner499dfcf2011-03-21 13:26:24 +0100170
Pablo Galindo526ef852019-10-08 21:38:11 +0100171 Py_INCREF(obj);
172 if (_PyObject_LookupAttrId(obj, &PyId___name__, &name) < 0) {
173 Py_DECREF(obj);
Serhiy Storchaka353053d2019-09-01 14:01:05 +0300174 return NULL;
175 }
Victor Stinner499dfcf2011-03-21 13:26:24 +0100176 if (name == NULL || !PyUnicode_Check(name)) {
Victor Stinner499dfcf2011-03-21 13:26:24 +0100177 repr = PyUnicode_FromFormat(
178 "<weakref at %p; to '%s' at %p>",
179 self,
180 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
Pablo Galindo526ef852019-10-08 21:38:11 +0100181 obj);
Fred Drake8844d522001-10-05 21:52:26 +0000182 }
183 else {
Victor Stinner499dfcf2011-03-21 13:26:24 +0100184 repr = PyUnicode_FromFormat(
185 "<weakref at %p; to '%s' at %p (%U)>",
186 self,
187 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
Pablo Galindo526ef852019-10-08 21:38:11 +0100188 obj,
Victor Stinner499dfcf2011-03-21 13:26:24 +0100189 name);
Fred Drake8844d522001-10-05 21:52:26 +0000190 }
Pablo Galindo526ef852019-10-08 21:38:11 +0100191 Py_DECREF(obj);
Victor Stinner499dfcf2011-03-21 13:26:24 +0100192 Py_XDECREF(name);
193 return repr;
Fred Drake8844d522001-10-05 21:52:26 +0000194}
195
196/* Weak references only support equality, not ordering. Two weak references
197 are equal if the underlying objects are equal. If the underlying object has
198 gone away, they are equal if they are identical. */
199
200static PyObject *
201weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
202{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000203 if ((op != Py_EQ && op != Py_NE) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000204 !PyWeakref_Check(self) ||
205 !PyWeakref_Check(other)) {
Brian Curtindfc80e32011-08-10 20:28:54 -0500206 Py_RETURN_NOTIMPLEMENTED;
Fred Drake8844d522001-10-05 21:52:26 +0000207 }
208 if (PyWeakref_GET_OBJECT(self) == Py_None
209 || PyWeakref_GET_OBJECT(other) == Py_None) {
Antoine Pitroue11fecb2012-11-11 19:36:51 +0100210 int res = (self == other);
211 if (op == Py_NE)
212 res = !res;
213 if (res)
214 Py_RETURN_TRUE;
215 else
216 Py_RETURN_FALSE;
Fred Drake8844d522001-10-05 21:52:26 +0000217 }
Pablo Galindo526ef852019-10-08 21:38:11 +0100218 PyObject* obj = PyWeakref_GET_OBJECT(self);
219 PyObject* other_obj = PyWeakref_GET_OBJECT(other);
220 Py_INCREF(obj);
221 Py_INCREF(other_obj);
222 PyObject* res = PyObject_RichCompare(obj, other_obj, op);
223 Py_DECREF(obj);
224 Py_DECREF(other_obj);
225 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000226}
227
Fred Drake0a4dd392004-07-02 18:57:45 +0000228/* Given the head of an object's list of weak references, extract the
229 * two callback-less refs (ref and proxy). Used to determine if the
230 * shared references exist and to determine the back link for newly
231 * inserted references.
232 */
233static void
234get_basic_refs(PyWeakReference *head,
235 PyWeakReference **refp, PyWeakReference **proxyp)
236{
237 *refp = NULL;
238 *proxyp = NULL;
239
240 if (head != NULL && head->wr_callback == NULL) {
241 /* We need to be careful that the "basic refs" aren't
242 subclasses of the main types. That complicates this a
243 little. */
244 if (PyWeakref_CheckRefExact(head)) {
245 *refp = head;
246 head = head->wr_next;
247 }
248 if (head != NULL
249 && head->wr_callback == NULL
250 && PyWeakref_CheckProxy(head)) {
251 *proxyp = head;
252 /* head = head->wr_next; */
253 }
254 }
255}
256
257/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
258static void
259insert_after(PyWeakReference *newref, PyWeakReference *prev)
260{
261 newref->wr_prev = prev;
262 newref->wr_next = prev->wr_next;
263 if (prev->wr_next != NULL)
264 prev->wr_next->wr_prev = newref;
265 prev->wr_next = newref;
266}
267
268/* Insert 'newref' at the head of the list; 'list' points to the variable
269 * that stores the head.
270 */
271static void
272insert_head(PyWeakReference *newref, PyWeakReference **list)
273{
274 PyWeakReference *next = *list;
275
276 newref->wr_prev = NULL;
277 newref->wr_next = next;
278 if (next != NULL)
279 next->wr_prev = newref;
280 *list = newref;
281}
282
283static int
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200284parse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs,
Fred Drake0a4dd392004-07-02 18:57:45 +0000285 PyObject **obp, PyObject **callbackp)
286{
Fred Drake0a4dd392004-07-02 18:57:45 +0000287 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
288}
289
290static PyObject *
291weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
292{
293 PyWeakReference *self = NULL;
294 PyObject *ob, *callback = NULL;
295
296 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
297 PyWeakReference *ref, *proxy;
298 PyWeakReference **list;
299
Christian Heimes90aa7642007-12-19 02:45:37 +0000300 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000301 PyErr_Format(PyExc_TypeError,
302 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000303 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000304 return NULL;
305 }
306 if (callback == Py_None)
307 callback = NULL;
308 list = GET_WEAKREFS_LISTPTR(ob);
309 get_basic_refs(*list, &ref, &proxy);
310 if (callback == NULL && type == &_PyWeakref_RefType) {
311 if (ref != NULL) {
312 /* We can re-use an existing reference. */
313 Py_INCREF(ref);
314 return (PyObject *)ref;
315 }
316 }
317 /* We have to create a new reference. */
318 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
319 list on ob can be mutated. This means that the ref and
320 proxy pointers we got back earlier may have been collected,
321 so we need to compute these values again before we use
322 them. */
323 self = (PyWeakReference *) (type->tp_alloc(type, 0));
324 if (self != NULL) {
325 init_weakref(self, ob, callback);
326 if (callback == NULL && type == &_PyWeakref_RefType) {
327 insert_head(self, list);
328 }
329 else {
330 PyWeakReference *prev;
331
332 get_basic_refs(*list, &ref, &proxy);
333 prev = (proxy == NULL) ? ref : proxy;
334 if (prev == NULL)
335 insert_head(self, list);
336 else
337 insert_after(self, prev);
338 }
339 }
340 }
341 return (PyObject *)self;
342}
343
344static int
345weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
346{
347 PyObject *tmp;
348
Serhiy Storchaka6cca5c82017-06-08 14:41:19 +0300349 if (!_PyArg_NoKeywords("ref", kwargs))
Serhiy Storchaka21eb4872016-05-07 15:41:09 +0300350 return -1;
351
Fred Drake0a4dd392004-07-02 18:57:45 +0000352 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
353 return 0;
354 else
Benjamin Peterson9aa42992008-09-10 21:57:34 +0000355 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000356}
357
Fred Drake8844d522001-10-05 21:52:26 +0000358
Mark Dickinson556e94b2013-04-13 15:45:44 +0100359static PyMemberDef weakref_members[] = {
360 {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY},
361 {NULL} /* Sentinel */
362};
363
Fred Drake8844d522001-10-05 21:52:26 +0000364PyTypeObject
365_PyWeakref_RefType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000366 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000367 "weakref",
368 sizeof(PyWeakReference),
369 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000370 weakref_dealloc, /*tp_dealloc*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200371 0, /*tp_vectorcall_offset*/
Fred Drake8844d522001-10-05 21:52:26 +0000372 0, /*tp_getattr*/
373 0, /*tp_setattr*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200374 0, /*tp_as_async*/
Fred Drake8844d522001-10-05 21:52:26 +0000375 (reprfunc)weakref_repr, /*tp_repr*/
376 0, /*tp_as_number*/
377 0, /*tp_as_sequence*/
378 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000379 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000380 (ternaryfunc)weakref_call, /*tp_call*/
381 0, /*tp_str*/
382 0, /*tp_getattro*/
383 0, /*tp_setattro*/
384 0, /*tp_as_buffer*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000385 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000386 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000387 0, /*tp_doc*/
388 (traverseproc)gc_traverse, /*tp_traverse*/
389 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000390 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000391 0, /*tp_weaklistoffset*/
392 0, /*tp_iter*/
393 0, /*tp_iternext*/
394 0, /*tp_methods*/
Mark Dickinson556e94b2013-04-13 15:45:44 +0100395 weakref_members, /*tp_members*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000396 0, /*tp_getset*/
397 0, /*tp_base*/
398 0, /*tp_dict*/
399 0, /*tp_descr_get*/
400 0, /*tp_descr_set*/
401 0, /*tp_dictoffset*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000402 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000403 PyType_GenericAlloc, /*tp_alloc*/
404 weakref___new__, /*tp_new*/
405 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000406};
407
408
409static int
410proxy_checkref(PyWeakReference *proxy)
411{
412 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
413 PyErr_SetString(PyExc_ReferenceError,
414 "weakly-referenced object no longer exists");
415 return 0;
416 }
417 return 1;
418}
419
420
Fred Drake73006d02001-10-18 18:04:18 +0000421/* If a parameter is a proxy, check that it is still "live" and wrap it,
422 * replacing the original value with the raw object. Raises ReferenceError
423 * if the param is a dead proxy.
424 */
425#define UNWRAP(o) \
426 if (PyWeakref_CheckProxy(o)) { \
427 if (!proxy_checkref((PyWeakReference *)o)) \
428 return NULL; \
429 o = PyWeakref_GET_OBJECT(o); \
430 }
431
Fred Drake8844d522001-10-05 21:52:26 +0000432#define WRAP_UNARY(method, generic) \
433 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000434 method(PyObject *proxy) { \
435 UNWRAP(proxy); \
Pablo Galindo526ef852019-10-08 21:38:11 +0100436 Py_INCREF(proxy); \
437 PyObject* res = generic(proxy); \
438 Py_DECREF(proxy); \
439 return res; \
Fred Drake8844d522001-10-05 21:52:26 +0000440 }
441
442#define WRAP_BINARY(method, generic) \
443 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000444 method(PyObject *x, PyObject *y) { \
445 UNWRAP(x); \
446 UNWRAP(y); \
Pablo Galindo526ef852019-10-08 21:38:11 +0100447 Py_INCREF(x); \
448 Py_INCREF(y); \
449 PyObject* res = generic(x, y); \
450 Py_DECREF(x); \
451 Py_DECREF(y); \
452 return res; \
Fred Drake8844d522001-10-05 21:52:26 +0000453 }
454
Fred Drake31f4d1f2001-10-18 19:21:46 +0000455/* Note that the third arg needs to be checked for NULL since the tp_call
456 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000457 */
Fred Drake8844d522001-10-05 21:52:26 +0000458#define WRAP_TERNARY(method, generic) \
459 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000460 method(PyObject *proxy, PyObject *v, PyObject *w) { \
461 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000462 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000463 if (w != NULL) \
464 UNWRAP(w); \
Pablo Galindo526ef852019-10-08 21:38:11 +0100465 Py_INCREF(proxy); \
466 Py_INCREF(v); \
467 Py_XINCREF(w); \
468 PyObject* res = generic(proxy, v, w); \
469 Py_DECREF(proxy); \
470 Py_DECREF(v); \
471 Py_XDECREF(w); \
472 return res; \
Fred Drake8844d522001-10-05 21:52:26 +0000473 }
474
Benjamin Peterson32019772009-11-19 03:08:32 +0000475#define WRAP_METHOD(method, special) \
476 static PyObject * \
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530477 method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200478 _Py_IDENTIFIER(special); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000479 UNWRAP(proxy); \
Pablo Galindo526ef852019-10-08 21:38:11 +0100480 Py_INCREF(proxy); \
481 PyObject* res = _PyObject_CallMethodId(proxy, &PyId_##special, NULL); \
482 Py_DECREF(proxy); \
483 return res; \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 }
Benjamin Peterson32019772009-11-19 03:08:32 +0000485
Fred Drake8844d522001-10-05 21:52:26 +0000486
487/* direct slots */
488
489WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
490WRAP_UNARY(proxy_str, PyObject_Str)
INADA Naoki72dccde2017-02-16 09:26:01 +0900491WRAP_TERNARY(proxy_call, PyObject_Call)
Fred Drake8844d522001-10-05 21:52:26 +0000492
Fred Drake8844d522001-10-05 21:52:26 +0000493static PyObject *
494proxy_repr(PyWeakReference *proxy)
495{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100496 return PyUnicode_FromFormat(
497 "<weakproxy at %p to %s at %p>",
498 proxy,
499 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
500 PyWeakref_GET_OBJECT(proxy));
Fred Drake8844d522001-10-05 21:52:26 +0000501}
502
503
504static int
505proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
506{
507 if (!proxy_checkref(proxy))
508 return -1;
Pablo Galindo526ef852019-10-08 21:38:11 +0100509 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
510 Py_INCREF(obj);
511 int res = PyObject_SetAttr(obj, name, value);
512 Py_DECREF(obj);
513 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000514}
515
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000516static PyObject *
517proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000518{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000519 UNWRAP(proxy);
520 UNWRAP(v);
521 return PyObject_RichCompare(proxy, v, op);
Fred Drake8844d522001-10-05 21:52:26 +0000522}
523
524/* number slots */
525WRAP_BINARY(proxy_add, PyNumber_Add)
526WRAP_BINARY(proxy_sub, PyNumber_Subtract)
527WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000528WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
529WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000530WRAP_BINARY(proxy_mod, PyNumber_Remainder)
531WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
532WRAP_TERNARY(proxy_pow, PyNumber_Power)
533WRAP_UNARY(proxy_neg, PyNumber_Negative)
534WRAP_UNARY(proxy_pos, PyNumber_Positive)
535WRAP_UNARY(proxy_abs, PyNumber_Absolute)
536WRAP_UNARY(proxy_invert, PyNumber_Invert)
537WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
538WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
539WRAP_BINARY(proxy_and, PyNumber_And)
540WRAP_BINARY(proxy_xor, PyNumber_Xor)
541WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000542WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000543WRAP_UNARY(proxy_float, PyNumber_Float)
544WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
545WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
546WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000547WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
548WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000549WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
550WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
551WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
552WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
553WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
554WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
555WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000556WRAP_UNARY(proxy_index, PyNumber_Index)
Mark Dickinson7abb6c02019-04-26 15:56:15 +0900557WRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply)
558WRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply)
Fred Drake8844d522001-10-05 21:52:26 +0000559
Tim Peters403a2032003-11-20 21:21:46 +0000560static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000561proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000562{
563 PyObject *o = PyWeakref_GET_OBJECT(proxy);
Pablo Galindo526ef852019-10-08 21:38:11 +0100564 if (!proxy_checkref(proxy)) {
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000565 return -1;
Pablo Galindo526ef852019-10-08 21:38:11 +0100566 }
567 Py_INCREF(o);
568 int res = PyObject_IsTrue(o);
569 Py_DECREF(o);
570 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000571}
572
Fred Drake0a4dd392004-07-02 18:57:45 +0000573static void
574proxy_dealloc(PyWeakReference *self)
575{
576 if (self->wr_callback != NULL)
577 PyObject_GC_UnTrack((PyObject *)self);
578 clear_weakref(self);
579 PyObject_GC_Del(self);
580}
581
Fred Drake8844d522001-10-05 21:52:26 +0000582/* sequence slots */
583
Fred Drake8844d522001-10-05 21:52:26 +0000584static int
585proxy_contains(PyWeakReference *proxy, PyObject *value)
586{
587 if (!proxy_checkref(proxy))
588 return -1;
Fred Drake8844d522001-10-05 21:52:26 +0000589
Pablo Galindo526ef852019-10-08 21:38:11 +0100590 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
591 Py_INCREF(obj);
592 int res = PySequence_Contains(obj, value);
593 Py_DECREF(obj);
594 return res;
595}
Fred Drake8844d522001-10-05 21:52:26 +0000596
597/* mapping slots */
598
Martin v. Löwis18e16552006-02-15 17:27:45 +0000599static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000600proxy_length(PyWeakReference *proxy)
601{
602 if (!proxy_checkref(proxy))
603 return -1;
Pablo Galindo526ef852019-10-08 21:38:11 +0100604
605 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
606 Py_INCREF(obj);
607 Py_ssize_t res = PyObject_Length(obj);
608 Py_DECREF(obj);
609 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000610}
611
612WRAP_BINARY(proxy_getitem, PyObject_GetItem)
613
614static int
615proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
616{
617 if (!proxy_checkref(proxy))
618 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000619
Pablo Galindo526ef852019-10-08 21:38:11 +0100620 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
621 Py_INCREF(obj);
622 int res;
623 if (value == NULL) {
624 res = PyObject_DelItem(obj, key);
625 } else {
626 res = PyObject_SetItem(obj, key, value);
627 }
628 Py_DECREF(obj);
629 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000630}
631
Fred Drakef16c3dc2002-08-09 18:34:16 +0000632/* iterator slots */
633
634static PyObject *
635proxy_iter(PyWeakReference *proxy)
636{
637 if (!proxy_checkref(proxy))
638 return NULL;
Pablo Galindo526ef852019-10-08 21:38:11 +0100639 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
640 Py_INCREF(obj);
641 PyObject* res = PyObject_GetIter(obj);
642 Py_DECREF(obj);
643 return res;
Fred Drakef16c3dc2002-08-09 18:34:16 +0000644}
645
646static PyObject *
647proxy_iternext(PyWeakReference *proxy)
648{
649 if (!proxy_checkref(proxy))
650 return NULL;
Pablo Galindo526ef852019-10-08 21:38:11 +0100651
652 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
653 Py_INCREF(obj);
654 PyObject* res = PyIter_Next(obj);
655 Py_DECREF(obj);
656 return res;
Fred Drakef16c3dc2002-08-09 18:34:16 +0000657}
658
Fred Drake8844d522001-10-05 21:52:26 +0000659
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200660WRAP_METHOD(proxy_bytes, __bytes__)
Benjamin Peterson32019772009-11-19 03:08:32 +0000661
662
663static PyMethodDef proxy_methods[] = {
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530664 {"__bytes__", proxy_bytes, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000665 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000666};
667
668
Fred Drake8844d522001-10-05 21:52:26 +0000669static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000670 proxy_add, /*nb_add*/
671 proxy_sub, /*nb_subtract*/
672 proxy_mul, /*nb_multiply*/
673 proxy_mod, /*nb_remainder*/
674 proxy_divmod, /*nb_divmod*/
675 proxy_pow, /*nb_power*/
676 proxy_neg, /*nb_negative*/
677 proxy_pos, /*nb_positive*/
678 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000679 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000680 proxy_invert, /*nb_invert*/
681 proxy_lshift, /*nb_lshift*/
682 proxy_rshift, /*nb_rshift*/
683 proxy_and, /*nb_and*/
684 proxy_xor, /*nb_xor*/
685 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000686 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000687 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000688 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000689 proxy_iadd, /*nb_inplace_add*/
690 proxy_isub, /*nb_inplace_subtract*/
691 proxy_imul, /*nb_inplace_multiply*/
692 proxy_imod, /*nb_inplace_remainder*/
693 proxy_ipow, /*nb_inplace_power*/
694 proxy_ilshift, /*nb_inplace_lshift*/
695 proxy_irshift, /*nb_inplace_rshift*/
696 proxy_iand, /*nb_inplace_and*/
697 proxy_ixor, /*nb_inplace_xor*/
698 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000699 proxy_floor_div, /*nb_floor_divide*/
700 proxy_true_div, /*nb_true_divide*/
701 proxy_ifloor_div, /*nb_inplace_floor_divide*/
702 proxy_itrue_div, /*nb_inplace_true_divide*/
703 proxy_index, /*nb_index*/
Mark Dickinson7abb6c02019-04-26 15:56:15 +0900704 proxy_matmul, /*nb_matrix_multiply*/
705 proxy_imatmul, /*nb_inplace_matrix_multiply*/
Fred Drake8844d522001-10-05 21:52:26 +0000706};
707
708static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000709 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000710 0, /*sq_concat*/
711 0, /*sq_repeat*/
712 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000713 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000714 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000716 (objobjproc)proxy_contains, /* sq_contains */
717};
718
719static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000720 (lenfunc)proxy_length, /*mp_length*/
721 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000722 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
723};
724
725
726PyTypeObject
727_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000728 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000729 "weakproxy",
730 sizeof(PyWeakReference),
731 0,
732 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000733 (destructor)proxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200734 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 0, /* tp_getattr */
736 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200737 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738 (reprfunc)proxy_repr, /* tp_repr */
739 &proxy_as_number, /* tp_as_number */
740 &proxy_as_sequence, /* tp_as_sequence */
741 &proxy_as_mapping, /* tp_as_mapping */
742 0, /* tp_hash */
743 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000744 proxy_str, /* tp_str */
745 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000746 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000747 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000748 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000749 0, /* tp_doc */
750 (traverseproc)gc_traverse, /* tp_traverse */
751 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000752 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000753 0, /* tp_weaklistoffset */
754 (getiterfunc)proxy_iter, /* tp_iter */
755 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000757};
758
759
760PyTypeObject
761_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000762 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000763 "weakcallableproxy",
764 sizeof(PyWeakReference),
765 0,
766 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000767 (destructor)proxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200768 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 0, /* tp_getattr */
770 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200771 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000772 (unaryfunc)proxy_repr, /* tp_repr */
773 &proxy_as_number, /* tp_as_number */
774 &proxy_as_sequence, /* tp_as_sequence */
775 &proxy_as_mapping, /* tp_as_mapping */
776 0, /* tp_hash */
777 proxy_call, /* tp_call */
778 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000779 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000780 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000781 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000782 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000783 0, /* tp_doc */
784 (traverseproc)gc_traverse, /* tp_traverse */
785 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000786 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000787 0, /* tp_weaklistoffset */
788 (getiterfunc)proxy_iter, /* tp_iter */
789 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000790};
791
792
Fred Drake8844d522001-10-05 21:52:26 +0000793
794PyObject *
795PyWeakref_NewRef(PyObject *ob, PyObject *callback)
796{
797 PyWeakReference *result = NULL;
798 PyWeakReference **list;
799 PyWeakReference *ref, *proxy;
800
Christian Heimes90aa7642007-12-19 02:45:37 +0000801 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000802 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000804 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000805 return NULL;
806 }
807 list = GET_WEAKREFS_LISTPTR(ob);
808 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000809 if (callback == Py_None)
810 callback = NULL;
811 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000812 /* return existing weak reference if it exists */
813 result = ref;
814 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000815 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000816 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000817 /* Note: new_weakref() can trigger cyclic GC, so the weakref
818 list on ob can be mutated. This means that the ref and
819 proxy pointers we got back earlier may have been collected,
820 so we need to compute these values again before we use
821 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000822 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000823 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000824 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000825 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000826 if (ref == NULL)
827 insert_head(result, list);
828 else {
829 /* Someone else added a ref without a callback
830 during GC. Return that one instead of this one
831 to avoid violating the invariants of the list
832 of weakrefs for ob. */
833 Py_DECREF(result);
834 Py_INCREF(ref);
835 result = ref;
836 }
Fred Drake8844d522001-10-05 21:52:26 +0000837 }
838 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000839 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000840
Fred Drakebc875f52004-02-04 23:14:14 +0000841 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000842 if (prev == NULL)
843 insert_head(result, list);
844 else
845 insert_after(result, prev);
846 }
Fred Drake8844d522001-10-05 21:52:26 +0000847 }
848 }
849 return (PyObject *) result;
850}
851
852
853PyObject *
854PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
855{
856 PyWeakReference *result = NULL;
857 PyWeakReference **list;
858 PyWeakReference *ref, *proxy;
859
Christian Heimes90aa7642007-12-19 02:45:37 +0000860 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000861 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000862 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000863 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000864 return NULL;
865 }
866 list = GET_WEAKREFS_LISTPTR(ob);
867 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000868 if (callback == Py_None)
869 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000870 if (callback == NULL)
871 /* attempt to return an existing weak reference if it exists */
872 result = proxy;
873 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000874 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000875 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000876 /* Note: new_weakref() can trigger cyclic GC, so the weakref
877 list on ob can be mutated. This means that the ref and
878 proxy pointers we got back earlier may have been collected,
879 so we need to compute these values again before we use
880 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000881 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000882 if (result != NULL) {
883 PyWeakReference *prev;
884
885 if (PyCallable_Check(ob))
Christian Heimes90aa7642007-12-19 02:45:37 +0000886 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000887 else
Christian Heimes90aa7642007-12-19 02:45:37 +0000888 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000889 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000890 if (callback == NULL) {
891 if (proxy != NULL) {
892 /* Someone else added a proxy without a callback
893 during GC. Return that one instead of this one
894 to avoid violating the invariants of the list
895 of weakrefs for ob. */
896 Py_DECREF(result);
Victor Stinnerb37672d2018-11-22 03:37:50 +0100897 result = proxy;
898 Py_INCREF(result);
Fred Drake6d3265d2004-08-03 14:47:25 +0000899 goto skip_insert;
900 }
Fred Drake8844d522001-10-05 21:52:26 +0000901 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000902 }
Fred Drake8844d522001-10-05 21:52:26 +0000903 else
904 prev = (proxy == NULL) ? ref : proxy;
905
906 if (prev == NULL)
907 insert_head(result, list);
908 else
909 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000910 skip_insert:
911 ;
Fred Drake8844d522001-10-05 21:52:26 +0000912 }
913 }
914 return (PyObject *) result;
915}
916
917
918PyObject *
919PyWeakref_GetObject(PyObject *ref)
920{
921 if (ref == NULL || !PyWeakref_Check(ref)) {
922 PyErr_BadInternalCall();
923 return NULL;
924 }
925 return PyWeakref_GET_OBJECT(ref);
926}
927
Tim Petersead8b7a2004-10-30 23:09:22 +0000928/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
929 * handle_weakrefs().
930 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000931static void
932handle_callback(PyWeakReference *ref, PyObject *callback)
933{
Victor Stinnerde4ae3d2016-12-04 22:59:09 +0100934 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000935
936 if (cbresult == NULL)
937 PyErr_WriteUnraisable(callback);
938 else
939 Py_DECREF(cbresult);
940}
941
942/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000943 *
944 * This iterates through the weak references for 'object' and calls callbacks
945 * for those references which have one. It returns when all callbacks have
946 * been attempted.
947 */
948void
949PyObject_ClearWeakRefs(PyObject *object)
950{
951 PyWeakReference **list;
952
953 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000954 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000955 || object->ob_refcnt != 0) {
956 PyErr_BadInternalCall();
957 return;
958 }
959 list = GET_WEAKREFS_LISTPTR(object);
960 /* Remove the callback-less basic and proxy references */
961 if (*list != NULL && (*list)->wr_callback == NULL) {
962 clear_weakref(*list);
963 if (*list != NULL && (*list)->wr_callback == NULL)
964 clear_weakref(*list);
965 }
966 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000967 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000968 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000969 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000970
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300971 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000972 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000973 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000974
Fred Drakeef8ebd12001-12-10 23:44:54 +0000975 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000976 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000977 if (callback != NULL) {
Benjamin Petersona38d1562008-06-16 20:47:12 +0000978 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000979 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000980 Py_DECREF(callback);
981 }
Fred Drake8844d522001-10-05 21:52:26 +0000982 }
983 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000984 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000985 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000986
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000987 tuple = PyTuple_New(count * 2);
988 if (tuple == NULL) {
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300989 _PyErr_ChainExceptions(err_type, err_value, err_tb);
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000990 return;
991 }
Fred Drake8844d522001-10-05 21:52:26 +0000992
993 for (i = 0; i < count; ++i) {
994 PyWeakReference *next = current->wr_next;
995
Benjamin Petersona38d1562008-06-16 20:47:12 +0000996 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000997 {
998 Py_INCREF(current);
999 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
1000 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
1001 }
1002 else {
1003 Py_DECREF(current->wr_callback);
1004 }
Fred Drake8844d522001-10-05 21:52:26 +00001005 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +00001006 clear_weakref(current);
1007 current = next;
1008 }
1009 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +00001010 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +00001011
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +00001012 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +00001013 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +00001014 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
1015 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +00001016 }
Fred Drake8844d522001-10-05 21:52:26 +00001017 }
1018 Py_DECREF(tuple);
1019 }
Serhiy Storchaka4aa86792015-03-30 09:52:29 +03001020 assert(!PyErr_Occurred());
1021 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +00001022 }
1023}