blob: c36d2395cc8c53901635dab012e3355bfe097cd3 [file] [log] [blame]
Fred Drake8844d522001-10-05 21:52:26 +00001#include "Python.h"
Victor Stinner4a21e572020-04-15 02:35:41 +02002#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR()
3#include "structmember.h" // PyMemberDef
Fred Drake8844d522001-10-05 21:52:26 +00004
5
6#define GET_WEAKREFS_LISTPTR(o) \
Victor Stinner38aefc52020-04-06 14:07:02 +02007 ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o))
Fred Drake8844d522001-10-05 21:52:26 +00008
Fred Drake8844d522001-10-05 21:52:26 +00009
Thomas Wouters0e3f5912006-08-11 14:57:12 +000010Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +000011_PyWeakref_GetWeakrefCount(PyWeakReference *head)
12{
Thomas Wouters0e3f5912006-08-11 14:57:12 +000013 Py_ssize_t count = 0;
Fred Drake8844d522001-10-05 21:52:26 +000014
15 while (head != NULL) {
16 ++count;
17 head = head->wr_next;
18 }
19 return count;
20}
21
22
Fred Drake0a4dd392004-07-02 18:57:45 +000023static void
24init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
25{
26 self->hash = -1;
27 self->wr_object = ob;
Xiang Zhangd0e82122017-02-20 12:25:16 +080028 self->wr_prev = NULL;
29 self->wr_next = NULL;
Fred Drake0a4dd392004-07-02 18:57:45 +000030 Py_XINCREF(callback);
31 self->wr_callback = callback;
32}
33
Fred Drake8844d522001-10-05 21:52:26 +000034static PyWeakReference *
Neil Schemenauer38a89162002-03-27 15:18:21 +000035new_weakref(PyObject *ob, PyObject *callback)
Fred Drake8844d522001-10-05 21:52:26 +000036{
37 PyWeakReference *result;
38
Neil Schemenauer38a89162002-03-27 15:18:21 +000039 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
40 if (result) {
Fred Drake0a4dd392004-07-02 18:57:45 +000041 init_weakref(result, ob, callback);
Neil Schemenauer38a89162002-03-27 15:18:21 +000042 PyObject_GC_Track(result);
43 }
Fred Drake8844d522001-10-05 21:52:26 +000044 return result;
45}
46
47
48/* This function clears the passed-in reference and removes it from the
49 * list of weak references for the referent. This is the only code that
50 * removes an item from the doubly-linked list of weak references for an
51 * object; it is also responsible for clearing the callback slot.
52 */
53static void
54clear_weakref(PyWeakReference *self)
55{
56 PyObject *callback = self->wr_callback;
57
Antoine Pitrou62a0d6e2012-12-08 21:15:26 +010058 if (self->wr_object != Py_None) {
59 PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
Fred Drake8844d522001-10-05 21:52:26 +000060
61 if (*list == self)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000062 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
63 then the weakref list itself (and thus the value of *list) will
64 end up being set to NULL. */
Fred Drake8844d522001-10-05 21:52:26 +000065 *list = self->wr_next;
66 self->wr_object = Py_None;
Fred Drake8844d522001-10-05 21:52:26 +000067 if (self->wr_prev != NULL)
68 self->wr_prev->wr_next = self->wr_next;
69 if (self->wr_next != NULL)
70 self->wr_next->wr_prev = self->wr_prev;
71 self->wr_prev = NULL;
72 self->wr_next = NULL;
Tim Peters403a2032003-11-20 21:21:46 +000073 }
74 if (callback != NULL) {
75 Py_DECREF(callback);
76 self->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +000077 }
78}
79
Tim Peters403a2032003-11-20 21:21:46 +000080/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
81 * the callback intact and uncalled. It must be possible to call self's
82 * tp_dealloc() after calling this, so self has to be left in a sane enough
83 * state for that to work. We expect tp_dealloc to decref the callback
84 * then. The reason for not letting clear_weakref() decref the callback
85 * right now is that if the callback goes away, that may in turn trigger
86 * another callback (if a weak reference to the callback exists) -- running
87 * arbitrary Python code in the middle of gc is a disaster. The convolution
88 * here allows gc to delay triggering such callbacks until the world is in
89 * a sane state again.
90 */
91void
92_PyWeakref_ClearRef(PyWeakReference *self)
93{
94 PyObject *callback;
95
96 assert(self != NULL);
97 assert(PyWeakref_Check(self));
98 /* Preserve and restore the callback around clear_weakref. */
99 callback = self->wr_callback;
100 self->wr_callback = NULL;
101 clear_weakref(self);
102 self->wr_callback = callback;
103}
Fred Drake8844d522001-10-05 21:52:26 +0000104
105static void
Fred Drake0a4dd392004-07-02 18:57:45 +0000106weakref_dealloc(PyObject *self)
Fred Drake8844d522001-10-05 21:52:26 +0000107{
Fred Drake0a4dd392004-07-02 18:57:45 +0000108 PyObject_GC_UnTrack(self);
109 clear_weakref((PyWeakReference *) self);
Christian Heimes90aa7642007-12-19 02:45:37 +0000110 Py_TYPE(self)->tp_free(self);
Fred Drake8844d522001-10-05 21:52:26 +0000111}
112
113
114static int
115gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
116{
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000117 Py_VISIT(self->wr_callback);
Fred Drake8844d522001-10-05 21:52:26 +0000118 return 0;
119}
120
121
122static int
123gc_clear(PyWeakReference *self)
124{
125 clear_weakref(self);
126 return 0;
127}
128
129
130static PyObject *
131weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
132{
Martin v. Löwis15e62742006-02-27 16:46:16 +0000133 static char *kwlist[] = {NULL};
Fred Drake8844d522001-10-05 21:52:26 +0000134
Martin v. Löwis15e62742006-02-27 16:46:16 +0000135 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
Fred Drake8844d522001-10-05 21:52:26 +0000136 PyObject *object = PyWeakref_GET_OBJECT(self);
137 Py_INCREF(object);
138 return (object);
139 }
140 return NULL;
141}
142
143
Benjamin Peterson8f67d082010-10-17 20:54:53 +0000144static Py_hash_t
Fred Drake8844d522001-10-05 21:52:26 +0000145weakref_hash(PyWeakReference *self)
146{
147 if (self->hash != -1)
148 return self->hash;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100149 PyObject* obj = PyWeakref_GET_OBJECT(self);
150 if (obj == Py_None) {
Fred Drake8844d522001-10-05 21:52:26 +0000151 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
152 return -1;
153 }
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100154 Py_INCREF(obj);
155 self->hash = PyObject_Hash(obj);
156 Py_DECREF(obj);
Fred Drake8844d522001-10-05 21:52:26 +0000157 return self->hash;
158}
Tim Peters403a2032003-11-20 21:21:46 +0000159
Fred Drake8844d522001-10-05 21:52:26 +0000160
161static PyObject *
162weakref_repr(PyWeakReference *self)
163{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100164 PyObject *name, *repr;
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200165 _Py_IDENTIFIER(__name__);
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100166 PyObject* obj = PyWeakref_GET_OBJECT(self);
Victor Stinner499dfcf2011-03-21 13:26:24 +0100167
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100168 if (obj == Py_None) {
Victor Stinner499dfcf2011-03-21 13:26:24 +0100169 return PyUnicode_FromFormat("<weakref at %p; dead>", self);
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100170 }
Victor Stinner499dfcf2011-03-21 13:26:24 +0100171
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100172 Py_INCREF(obj);
173 if (_PyObject_LookupAttrId(obj, &PyId___name__, &name) < 0) {
174 Py_DECREF(obj);
Serhiy Storchaka41c57b32019-09-01 12:03:39 +0300175 return NULL;
176 }
Victor Stinner499dfcf2011-03-21 13:26:24 +0100177 if (name == NULL || !PyUnicode_Check(name)) {
Victor Stinner499dfcf2011-03-21 13:26:24 +0100178 repr = PyUnicode_FromFormat(
179 "<weakref at %p; to '%s' at %p>",
180 self,
181 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100182 obj);
Fred Drake8844d522001-10-05 21:52:26 +0000183 }
184 else {
Victor Stinner499dfcf2011-03-21 13:26:24 +0100185 repr = PyUnicode_FromFormat(
186 "<weakref at %p; to '%s' at %p (%U)>",
187 self,
188 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100189 obj,
Victor Stinner499dfcf2011-03-21 13:26:24 +0100190 name);
Fred Drake8844d522001-10-05 21:52:26 +0000191 }
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100192 Py_DECREF(obj);
Victor Stinner499dfcf2011-03-21 13:26:24 +0100193 Py_XDECREF(name);
194 return repr;
Fred Drake8844d522001-10-05 21:52:26 +0000195}
196
197/* Weak references only support equality, not ordering. Two weak references
198 are equal if the underlying objects are equal. If the underlying object has
199 gone away, they are equal if they are identical. */
200
201static PyObject *
202weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
203{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000204 if ((op != Py_EQ && op != Py_NE) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 !PyWeakref_Check(self) ||
206 !PyWeakref_Check(other)) {
Brian Curtindfc80e32011-08-10 20:28:54 -0500207 Py_RETURN_NOTIMPLEMENTED;
Fred Drake8844d522001-10-05 21:52:26 +0000208 }
209 if (PyWeakref_GET_OBJECT(self) == Py_None
210 || PyWeakref_GET_OBJECT(other) == Py_None) {
Antoine Pitroue11fecb2012-11-11 19:36:51 +0100211 int res = (self == other);
212 if (op == Py_NE)
213 res = !res;
214 if (res)
215 Py_RETURN_TRUE;
216 else
217 Py_RETURN_FALSE;
Fred Drake8844d522001-10-05 21:52:26 +0000218 }
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100219 PyObject* obj = PyWeakref_GET_OBJECT(self);
220 PyObject* other_obj = PyWeakref_GET_OBJECT(other);
221 Py_INCREF(obj);
222 Py_INCREF(other_obj);
223 PyObject* res = PyObject_RichCompare(obj, other_obj, op);
224 Py_DECREF(obj);
225 Py_DECREF(other_obj);
226 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000227}
228
Fred Drake0a4dd392004-07-02 18:57:45 +0000229/* Given the head of an object's list of weak references, extract the
230 * two callback-less refs (ref and proxy). Used to determine if the
231 * shared references exist and to determine the back link for newly
232 * inserted references.
233 */
234static void
235get_basic_refs(PyWeakReference *head,
236 PyWeakReference **refp, PyWeakReference **proxyp)
237{
238 *refp = NULL;
239 *proxyp = NULL;
240
241 if (head != NULL && head->wr_callback == NULL) {
242 /* We need to be careful that the "basic refs" aren't
243 subclasses of the main types. That complicates this a
244 little. */
245 if (PyWeakref_CheckRefExact(head)) {
246 *refp = head;
247 head = head->wr_next;
248 }
249 if (head != NULL
250 && head->wr_callback == NULL
251 && PyWeakref_CheckProxy(head)) {
252 *proxyp = head;
253 /* head = head->wr_next; */
254 }
255 }
256}
257
258/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
259static void
260insert_after(PyWeakReference *newref, PyWeakReference *prev)
261{
262 newref->wr_prev = prev;
263 newref->wr_next = prev->wr_next;
264 if (prev->wr_next != NULL)
265 prev->wr_next->wr_prev = newref;
266 prev->wr_next = newref;
267}
268
269/* Insert 'newref' at the head of the list; 'list' points to the variable
270 * that stores the head.
271 */
272static void
273insert_head(PyWeakReference *newref, PyWeakReference **list)
274{
275 PyWeakReference *next = *list;
276
277 newref->wr_prev = NULL;
278 newref->wr_next = next;
279 if (next != NULL)
280 next->wr_prev = newref;
281 *list = newref;
282}
283
284static int
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200285parse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs,
Fred Drake0a4dd392004-07-02 18:57:45 +0000286 PyObject **obp, PyObject **callbackp)
287{
Fred Drake0a4dd392004-07-02 18:57:45 +0000288 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
289}
290
291static PyObject *
292weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
293{
294 PyWeakReference *self = NULL;
295 PyObject *ob, *callback = NULL;
296
297 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
298 PyWeakReference *ref, *proxy;
299 PyWeakReference **list;
300
Christian Heimes90aa7642007-12-19 02:45:37 +0000301 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000302 PyErr_Format(PyExc_TypeError,
303 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000304 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000305 return NULL;
306 }
307 if (callback == Py_None)
308 callback = NULL;
309 list = GET_WEAKREFS_LISTPTR(ob);
310 get_basic_refs(*list, &ref, &proxy);
311 if (callback == NULL && type == &_PyWeakref_RefType) {
312 if (ref != NULL) {
313 /* We can re-use an existing reference. */
314 Py_INCREF(ref);
315 return (PyObject *)ref;
316 }
317 }
318 /* We have to create a new reference. */
319 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
320 list on ob can be mutated. This means that the ref and
321 proxy pointers we got back earlier may have been collected,
322 so we need to compute these values again before we use
323 them. */
324 self = (PyWeakReference *) (type->tp_alloc(type, 0));
325 if (self != NULL) {
326 init_weakref(self, ob, callback);
327 if (callback == NULL && type == &_PyWeakref_RefType) {
328 insert_head(self, list);
329 }
330 else {
331 PyWeakReference *prev;
332
333 get_basic_refs(*list, &ref, &proxy);
334 prev = (proxy == NULL) ? ref : proxy;
335 if (prev == NULL)
336 insert_head(self, list);
337 else
338 insert_after(self, prev);
339 }
340 }
341 }
342 return (PyObject *)self;
343}
344
345static int
346weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
347{
348 PyObject *tmp;
349
Serhiy Storchaka6cca5c82017-06-08 14:41:19 +0300350 if (!_PyArg_NoKeywords("ref", kwargs))
Serhiy Storchaka21eb4872016-05-07 15:41:09 +0300351 return -1;
352
Fred Drake0a4dd392004-07-02 18:57:45 +0000353 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
354 return 0;
355 else
Benjamin Peterson9aa42992008-09-10 21:57:34 +0000356 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000357}
358
Fred Drake8844d522001-10-05 21:52:26 +0000359
Mark Dickinson556e94b2013-04-13 15:45:44 +0100360static PyMemberDef weakref_members[] = {
361 {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY},
362 {NULL} /* Sentinel */
363};
364
Ethan Smith8ef87502020-04-13 21:54:40 -0700365static PyMethodDef weakref_methods[] = {
366 {"__class_getitem__", (PyCFunction)Py_GenericAlias,
367 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
368 {NULL} /* Sentinel */
369};
370
Fred Drake8844d522001-10-05 21:52:26 +0000371PyTypeObject
372_PyWeakref_RefType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000373 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000374 "weakref",
375 sizeof(PyWeakReference),
376 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000377 weakref_dealloc, /*tp_dealloc*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200378 0, /*tp_vectorcall_offset*/
Fred Drake8844d522001-10-05 21:52:26 +0000379 0, /*tp_getattr*/
380 0, /*tp_setattr*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200381 0, /*tp_as_async*/
Fred Drake8844d522001-10-05 21:52:26 +0000382 (reprfunc)weakref_repr, /*tp_repr*/
383 0, /*tp_as_number*/
384 0, /*tp_as_sequence*/
385 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000386 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000387 (ternaryfunc)weakref_call, /*tp_call*/
388 0, /*tp_str*/
389 0, /*tp_getattro*/
390 0, /*tp_setattro*/
391 0, /*tp_as_buffer*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000392 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000393 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000394 0, /*tp_doc*/
395 (traverseproc)gc_traverse, /*tp_traverse*/
396 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000398 0, /*tp_weaklistoffset*/
399 0, /*tp_iter*/
400 0, /*tp_iternext*/
Ethan Smith8ef87502020-04-13 21:54:40 -0700401 weakref_methods, /*tp_methods*/
Mark Dickinson556e94b2013-04-13 15:45:44 +0100402 weakref_members, /*tp_members*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000403 0, /*tp_getset*/
404 0, /*tp_base*/
405 0, /*tp_dict*/
406 0, /*tp_descr_get*/
407 0, /*tp_descr_set*/
408 0, /*tp_dictoffset*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000409 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000410 PyType_GenericAlloc, /*tp_alloc*/
411 weakref___new__, /*tp_new*/
412 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000413};
414
415
416static int
417proxy_checkref(PyWeakReference *proxy)
418{
419 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
420 PyErr_SetString(PyExc_ReferenceError,
421 "weakly-referenced object no longer exists");
422 return 0;
423 }
424 return 1;
425}
426
427
Fred Drake73006d02001-10-18 18:04:18 +0000428/* If a parameter is a proxy, check that it is still "live" and wrap it,
429 * replacing the original value with the raw object. Raises ReferenceError
430 * if the param is a dead proxy.
431 */
432#define UNWRAP(o) \
433 if (PyWeakref_CheckProxy(o)) { \
434 if (!proxy_checkref((PyWeakReference *)o)) \
435 return NULL; \
436 o = PyWeakref_GET_OBJECT(o); \
437 }
438
Fred Drake8844d522001-10-05 21:52:26 +0000439#define WRAP_UNARY(method, generic) \
440 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000441 method(PyObject *proxy) { \
442 UNWRAP(proxy); \
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100443 Py_INCREF(proxy); \
444 PyObject* res = generic(proxy); \
445 Py_DECREF(proxy); \
446 return res; \
Fred Drake8844d522001-10-05 21:52:26 +0000447 }
448
449#define WRAP_BINARY(method, generic) \
450 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000451 method(PyObject *x, PyObject *y) { \
452 UNWRAP(x); \
453 UNWRAP(y); \
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100454 Py_INCREF(x); \
455 Py_INCREF(y); \
456 PyObject* res = generic(x, y); \
457 Py_DECREF(x); \
458 Py_DECREF(y); \
459 return res; \
Fred Drake8844d522001-10-05 21:52:26 +0000460 }
461
Fred Drake31f4d1f2001-10-18 19:21:46 +0000462/* Note that the third arg needs to be checked for NULL since the tp_call
463 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000464 */
Fred Drake8844d522001-10-05 21:52:26 +0000465#define WRAP_TERNARY(method, generic) \
466 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000467 method(PyObject *proxy, PyObject *v, PyObject *w) { \
468 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000469 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000470 if (w != NULL) \
471 UNWRAP(w); \
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100472 Py_INCREF(proxy); \
473 Py_INCREF(v); \
474 Py_XINCREF(w); \
475 PyObject* res = generic(proxy, v, w); \
476 Py_DECREF(proxy); \
477 Py_DECREF(v); \
478 Py_XDECREF(w); \
479 return res; \
Fred Drake8844d522001-10-05 21:52:26 +0000480 }
481
Benjamin Peterson32019772009-11-19 03:08:32 +0000482#define WRAP_METHOD(method, special) \
483 static PyObject * \
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530484 method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200485 _Py_IDENTIFIER(special); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 UNWRAP(proxy); \
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100487 Py_INCREF(proxy); \
488 PyObject* res = _PyObject_CallMethodIdNoArgs(proxy, &PyId_##special); \
489 Py_DECREF(proxy); \
490 return res; \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000491 }
Benjamin Peterson32019772009-11-19 03:08:32 +0000492
Fred Drake8844d522001-10-05 21:52:26 +0000493
494/* direct slots */
495
496WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
497WRAP_UNARY(proxy_str, PyObject_Str)
INADA Naoki72dccde2017-02-16 09:26:01 +0900498WRAP_TERNARY(proxy_call, PyObject_Call)
Fred Drake8844d522001-10-05 21:52:26 +0000499
Fred Drake8844d522001-10-05 21:52:26 +0000500static PyObject *
501proxy_repr(PyWeakReference *proxy)
502{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100503 return PyUnicode_FromFormat(
504 "<weakproxy at %p to %s at %p>",
505 proxy,
506 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
507 PyWeakref_GET_OBJECT(proxy));
Fred Drake8844d522001-10-05 21:52:26 +0000508}
509
510
511static int
512proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
513{
514 if (!proxy_checkref(proxy))
515 return -1;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100516 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
517 Py_INCREF(obj);
518 int res = PyObject_SetAttr(obj, name, value);
519 Py_DECREF(obj);
520 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000521}
522
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000523static PyObject *
524proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000525{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000526 UNWRAP(proxy);
527 UNWRAP(v);
528 return PyObject_RichCompare(proxy, v, op);
Fred Drake8844d522001-10-05 21:52:26 +0000529}
530
531/* number slots */
532WRAP_BINARY(proxy_add, PyNumber_Add)
533WRAP_BINARY(proxy_sub, PyNumber_Subtract)
534WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000535WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
536WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000537WRAP_BINARY(proxy_mod, PyNumber_Remainder)
538WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
539WRAP_TERNARY(proxy_pow, PyNumber_Power)
540WRAP_UNARY(proxy_neg, PyNumber_Negative)
541WRAP_UNARY(proxy_pos, PyNumber_Positive)
542WRAP_UNARY(proxy_abs, PyNumber_Absolute)
543WRAP_UNARY(proxy_invert, PyNumber_Invert)
544WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
545WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
546WRAP_BINARY(proxy_and, PyNumber_And)
547WRAP_BINARY(proxy_xor, PyNumber_Xor)
548WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000549WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000550WRAP_UNARY(proxy_float, PyNumber_Float)
551WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
552WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
553WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000554WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
555WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000556WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
557WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
558WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
559WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
560WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
561WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
562WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000563WRAP_UNARY(proxy_index, PyNumber_Index)
Mark Dickinson7abb6c02019-04-26 15:56:15 +0900564WRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply)
565WRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply)
Fred Drake8844d522001-10-05 21:52:26 +0000566
Tim Peters403a2032003-11-20 21:21:46 +0000567static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000568proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000569{
570 PyObject *o = PyWeakref_GET_OBJECT(proxy);
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100571 if (!proxy_checkref(proxy)) {
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000572 return -1;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100573 }
574 Py_INCREF(o);
575 int res = PyObject_IsTrue(o);
576 Py_DECREF(o);
577 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000578}
579
Fred Drake0a4dd392004-07-02 18:57:45 +0000580static void
581proxy_dealloc(PyWeakReference *self)
582{
583 if (self->wr_callback != NULL)
584 PyObject_GC_UnTrack((PyObject *)self);
585 clear_weakref(self);
586 PyObject_GC_Del(self);
587}
588
Fred Drake8844d522001-10-05 21:52:26 +0000589/* sequence slots */
590
Fred Drake8844d522001-10-05 21:52:26 +0000591static int
592proxy_contains(PyWeakReference *proxy, PyObject *value)
593{
594 if (!proxy_checkref(proxy))
595 return -1;
Fred Drake8844d522001-10-05 21:52:26 +0000596
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100597 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
598 Py_INCREF(obj);
599 int res = PySequence_Contains(obj, value);
600 Py_DECREF(obj);
601 return res;
602}
Fred Drake8844d522001-10-05 21:52:26 +0000603
604/* mapping slots */
605
Martin v. Löwis18e16552006-02-15 17:27:45 +0000606static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000607proxy_length(PyWeakReference *proxy)
608{
609 if (!proxy_checkref(proxy))
610 return -1;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100611
612 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
613 Py_INCREF(obj);
614 Py_ssize_t res = PyObject_Length(obj);
615 Py_DECREF(obj);
616 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000617}
618
619WRAP_BINARY(proxy_getitem, PyObject_GetItem)
620
621static int
622proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
623{
624 if (!proxy_checkref(proxy))
625 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000626
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100627 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
628 Py_INCREF(obj);
629 int res;
630 if (value == NULL) {
631 res = PyObject_DelItem(obj, key);
632 } else {
633 res = PyObject_SetItem(obj, key, value);
634 }
635 Py_DECREF(obj);
636 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000637}
638
Fred Drakef16c3dc2002-08-09 18:34:16 +0000639/* iterator slots */
640
641static PyObject *
642proxy_iter(PyWeakReference *proxy)
643{
644 if (!proxy_checkref(proxy))
645 return NULL;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100646 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
647 Py_INCREF(obj);
648 PyObject* res = PyObject_GetIter(obj);
649 Py_DECREF(obj);
650 return res;
Fred Drakef16c3dc2002-08-09 18:34:16 +0000651}
652
653static PyObject *
654proxy_iternext(PyWeakReference *proxy)
655{
656 if (!proxy_checkref(proxy))
657 return NULL;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100658
659 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
660 Py_INCREF(obj);
661 PyObject* res = PyIter_Next(obj);
662 Py_DECREF(obj);
663 return res;
Fred Drakef16c3dc2002-08-09 18:34:16 +0000664}
665
Fred Drake8844d522001-10-05 21:52:26 +0000666
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200667WRAP_METHOD(proxy_bytes, __bytes__)
Pablo Galindo96074de2020-05-05 22:58:19 +0100668WRAP_METHOD(proxy_reversed, __reversed__)
Benjamin Peterson32019772009-11-19 03:08:32 +0000669
670
671static PyMethodDef proxy_methods[] = {
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530672 {"__bytes__", proxy_bytes, METH_NOARGS},
Pablo Galindo96074de2020-05-05 22:58:19 +0100673 {"__reversed__", proxy_reversed, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000675};
676
677
Fred Drake8844d522001-10-05 21:52:26 +0000678static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000679 proxy_add, /*nb_add*/
680 proxy_sub, /*nb_subtract*/
681 proxy_mul, /*nb_multiply*/
682 proxy_mod, /*nb_remainder*/
683 proxy_divmod, /*nb_divmod*/
684 proxy_pow, /*nb_power*/
685 proxy_neg, /*nb_negative*/
686 proxy_pos, /*nb_positive*/
687 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000688 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000689 proxy_invert, /*nb_invert*/
690 proxy_lshift, /*nb_lshift*/
691 proxy_rshift, /*nb_rshift*/
692 proxy_and, /*nb_and*/
693 proxy_xor, /*nb_xor*/
694 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000695 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000696 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000697 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000698 proxy_iadd, /*nb_inplace_add*/
699 proxy_isub, /*nb_inplace_subtract*/
700 proxy_imul, /*nb_inplace_multiply*/
701 proxy_imod, /*nb_inplace_remainder*/
702 proxy_ipow, /*nb_inplace_power*/
703 proxy_ilshift, /*nb_inplace_lshift*/
704 proxy_irshift, /*nb_inplace_rshift*/
705 proxy_iand, /*nb_inplace_and*/
706 proxy_ixor, /*nb_inplace_xor*/
707 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000708 proxy_floor_div, /*nb_floor_divide*/
709 proxy_true_div, /*nb_true_divide*/
710 proxy_ifloor_div, /*nb_inplace_floor_divide*/
711 proxy_itrue_div, /*nb_inplace_true_divide*/
712 proxy_index, /*nb_index*/
Mark Dickinson7abb6c02019-04-26 15:56:15 +0900713 proxy_matmul, /*nb_matrix_multiply*/
714 proxy_imatmul, /*nb_inplace_matrix_multiply*/
Fred Drake8844d522001-10-05 21:52:26 +0000715};
716
717static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000718 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000719 0, /*sq_concat*/
720 0, /*sq_repeat*/
721 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000722 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000723 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000724 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000725 (objobjproc)proxy_contains, /* sq_contains */
726};
727
728static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000729 (lenfunc)proxy_length, /*mp_length*/
730 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000731 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
732};
733
734
735PyTypeObject
736_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000737 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000738 "weakproxy",
739 sizeof(PyWeakReference),
740 0,
741 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000742 (destructor)proxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200743 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000744 0, /* tp_getattr */
745 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200746 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000747 (reprfunc)proxy_repr, /* tp_repr */
748 &proxy_as_number, /* tp_as_number */
749 &proxy_as_sequence, /* tp_as_sequence */
750 &proxy_as_mapping, /* tp_as_mapping */
Miss Islington (bot)2df13e12021-06-29 16:19:06 -0700751// Notice that tp_hash is intentionally omitted as proxies are "mutable" (when the reference dies).
752 0, /* tp_hash */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000753 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000754 proxy_str, /* tp_str */
755 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000756 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000758 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000759 0, /* tp_doc */
760 (traverseproc)gc_traverse, /* tp_traverse */
761 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000762 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000763 0, /* tp_weaklistoffset */
764 (getiterfunc)proxy_iter, /* tp_iter */
765 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000766 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000767};
768
769
770PyTypeObject
771_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000772 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000773 "weakcallableproxy",
774 sizeof(PyWeakReference),
775 0,
776 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000777 (destructor)proxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200778 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000779 0, /* tp_getattr */
780 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200781 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782 (unaryfunc)proxy_repr, /* tp_repr */
783 &proxy_as_number, /* tp_as_number */
784 &proxy_as_sequence, /* tp_as_sequence */
785 &proxy_as_mapping, /* tp_as_mapping */
786 0, /* tp_hash */
787 proxy_call, /* tp_call */
788 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000789 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000790 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000791 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000792 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000793 0, /* tp_doc */
794 (traverseproc)gc_traverse, /* tp_traverse */
795 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000796 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000797 0, /* tp_weaklistoffset */
798 (getiterfunc)proxy_iter, /* tp_iter */
799 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000800};
801
802
Fred Drake8844d522001-10-05 21:52:26 +0000803
804PyObject *
805PyWeakref_NewRef(PyObject *ob, PyObject *callback)
806{
807 PyWeakReference *result = NULL;
808 PyWeakReference **list;
809 PyWeakReference *ref, *proxy;
810
Christian Heimes90aa7642007-12-19 02:45:37 +0000811 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000812 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000813 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000814 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000815 return NULL;
816 }
817 list = GET_WEAKREFS_LISTPTR(ob);
818 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000819 if (callback == Py_None)
820 callback = NULL;
821 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000822 /* return existing weak reference if it exists */
823 result = ref;
824 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000825 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000826 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000827 /* Note: new_weakref() can trigger cyclic GC, so the weakref
828 list on ob can be mutated. This means that the ref and
829 proxy pointers we got back earlier may have been collected,
830 so we need to compute these values again before we use
831 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000832 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000833 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000834 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000835 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000836 if (ref == NULL)
837 insert_head(result, list);
838 else {
839 /* Someone else added a ref without a callback
840 during GC. Return that one instead of this one
841 to avoid violating the invariants of the list
842 of weakrefs for ob. */
843 Py_DECREF(result);
844 Py_INCREF(ref);
845 result = ref;
846 }
Fred Drake8844d522001-10-05 21:52:26 +0000847 }
848 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000849 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000850
Fred Drakebc875f52004-02-04 23:14:14 +0000851 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000852 if (prev == NULL)
853 insert_head(result, list);
854 else
855 insert_after(result, prev);
856 }
Fred Drake8844d522001-10-05 21:52:26 +0000857 }
858 }
859 return (PyObject *) result;
860}
861
862
863PyObject *
864PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
865{
866 PyWeakReference *result = NULL;
867 PyWeakReference **list;
868 PyWeakReference *ref, *proxy;
869
Christian Heimes90aa7642007-12-19 02:45:37 +0000870 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000871 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000872 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000873 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000874 return NULL;
875 }
876 list = GET_WEAKREFS_LISTPTR(ob);
877 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000878 if (callback == Py_None)
879 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000880 if (callback == NULL)
881 /* attempt to return an existing weak reference if it exists */
882 result = proxy;
883 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000884 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000885 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000886 /* Note: new_weakref() can trigger cyclic GC, so the weakref
887 list on ob can be mutated. This means that the ref and
888 proxy pointers we got back earlier may have been collected,
889 so we need to compute these values again before we use
890 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000891 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000892 if (result != NULL) {
893 PyWeakReference *prev;
894
Victor Stinnerd2ec81a2020-02-07 09:17:07 +0100895 if (PyCallable_Check(ob)) {
896 Py_SET_TYPE(result, &_PyWeakref_CallableProxyType);
897 }
898 else {
899 Py_SET_TYPE(result, &_PyWeakref_ProxyType);
900 }
Fred Drakebc875f52004-02-04 23:14:14 +0000901 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000902 if (callback == NULL) {
903 if (proxy != NULL) {
904 /* Someone else added a proxy without a callback
905 during GC. Return that one instead of this one
906 to avoid violating the invariants of the list
907 of weakrefs for ob. */
908 Py_DECREF(result);
Victor Stinnerb37672d2018-11-22 03:37:50 +0100909 result = proxy;
910 Py_INCREF(result);
Fred Drake6d3265d2004-08-03 14:47:25 +0000911 goto skip_insert;
912 }
Fred Drake8844d522001-10-05 21:52:26 +0000913 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000914 }
Fred Drake8844d522001-10-05 21:52:26 +0000915 else
916 prev = (proxy == NULL) ? ref : proxy;
917
918 if (prev == NULL)
919 insert_head(result, list);
920 else
921 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000922 skip_insert:
923 ;
Fred Drake8844d522001-10-05 21:52:26 +0000924 }
925 }
926 return (PyObject *) result;
927}
928
929
930PyObject *
931PyWeakref_GetObject(PyObject *ref)
932{
933 if (ref == NULL || !PyWeakref_Check(ref)) {
934 PyErr_BadInternalCall();
935 return NULL;
936 }
937 return PyWeakref_GET_OBJECT(ref);
938}
939
Tim Petersead8b7a2004-10-30 23:09:22 +0000940/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
941 * handle_weakrefs().
942 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000943static void
944handle_callback(PyWeakReference *ref, PyObject *callback)
945{
Petr Viktorinffd97532020-02-11 17:46:57 +0100946 PyObject *cbresult = PyObject_CallOneArg(callback, (PyObject *)ref);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000947
948 if (cbresult == NULL)
949 PyErr_WriteUnraisable(callback);
950 else
951 Py_DECREF(cbresult);
952}
953
954/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000955 *
956 * This iterates through the weak references for 'object' and calls callbacks
957 * for those references which have one. It returns when all callbacks have
958 * been attempted.
959 */
960void
961PyObject_ClearWeakRefs(PyObject *object)
962{
963 PyWeakReference **list;
964
965 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000966 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Victor Stinnera93c51e2020-02-07 00:38:59 +0100967 || Py_REFCNT(object) != 0)
968 {
Fred Drake8844d522001-10-05 21:52:26 +0000969 PyErr_BadInternalCall();
970 return;
971 }
972 list = GET_WEAKREFS_LISTPTR(object);
973 /* Remove the callback-less basic and proxy references */
974 if (*list != NULL && (*list)->wr_callback == NULL) {
975 clear_weakref(*list);
976 if (*list != NULL && (*list)->wr_callback == NULL)
977 clear_weakref(*list);
978 }
979 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000980 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000981 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000982 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000983
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300984 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000985 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000986 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000987
Fred Drakeef8ebd12001-12-10 23:44:54 +0000988 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000989 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000990 if (callback != NULL) {
Victor Stinnera93c51e2020-02-07 00:38:59 +0100991 if (Py_REFCNT((PyObject *)current) > 0) {
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000992 handle_callback(current, callback);
Victor Stinnera93c51e2020-02-07 00:38:59 +0100993 }
Fred Drake0a4dd392004-07-02 18:57:45 +0000994 Py_DECREF(callback);
995 }
Fred Drake8844d522001-10-05 21:52:26 +0000996 }
997 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000998 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000999 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001000
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +00001001 tuple = PyTuple_New(count * 2);
1002 if (tuple == NULL) {
Serhiy Storchaka4aa86792015-03-30 09:52:29 +03001003 _PyErr_ChainExceptions(err_type, err_value, err_tb);
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +00001004 return;
1005 }
Fred Drake8844d522001-10-05 21:52:26 +00001006
1007 for (i = 0; i < count; ++i) {
1008 PyWeakReference *next = current->wr_next;
1009
Victor Stinnera93c51e2020-02-07 00:38:59 +01001010 if (Py_REFCNT((PyObject *)current) > 0) {
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +00001011 Py_INCREF(current);
1012 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
1013 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
1014 }
1015 else {
1016 Py_DECREF(current->wr_callback);
1017 }
Fred Drake8844d522001-10-05 21:52:26 +00001018 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +00001019 clear_weakref(current);
1020 current = next;
1021 }
1022 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +00001023 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +00001024
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +00001025 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +00001026 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +00001027 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
1028 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +00001029 }
Fred Drake8844d522001-10-05 21:52:26 +00001030 }
1031 Py_DECREF(tuple);
1032 }
Serhiy Storchaka4aa86792015-03-30 09:52:29 +03001033 assert(!PyErr_Occurred());
1034 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +00001035 }
1036}