blob: 9640d93aaf2dafbdbfe66b8364167d0adb3339a0 [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__)
Benjamin Peterson32019772009-11-19 03:08:32 +0000668
669
670static PyMethodDef proxy_methods[] = {
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530671 {"__bytes__", proxy_bytes, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000673};
674
675
Fred Drake8844d522001-10-05 21:52:26 +0000676static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000677 proxy_add, /*nb_add*/
678 proxy_sub, /*nb_subtract*/
679 proxy_mul, /*nb_multiply*/
680 proxy_mod, /*nb_remainder*/
681 proxy_divmod, /*nb_divmod*/
682 proxy_pow, /*nb_power*/
683 proxy_neg, /*nb_negative*/
684 proxy_pos, /*nb_positive*/
685 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000686 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000687 proxy_invert, /*nb_invert*/
688 proxy_lshift, /*nb_lshift*/
689 proxy_rshift, /*nb_rshift*/
690 proxy_and, /*nb_and*/
691 proxy_xor, /*nb_xor*/
692 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000693 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000694 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000695 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000696 proxy_iadd, /*nb_inplace_add*/
697 proxy_isub, /*nb_inplace_subtract*/
698 proxy_imul, /*nb_inplace_multiply*/
699 proxy_imod, /*nb_inplace_remainder*/
700 proxy_ipow, /*nb_inplace_power*/
701 proxy_ilshift, /*nb_inplace_lshift*/
702 proxy_irshift, /*nb_inplace_rshift*/
703 proxy_iand, /*nb_inplace_and*/
704 proxy_ixor, /*nb_inplace_xor*/
705 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000706 proxy_floor_div, /*nb_floor_divide*/
707 proxy_true_div, /*nb_true_divide*/
708 proxy_ifloor_div, /*nb_inplace_floor_divide*/
709 proxy_itrue_div, /*nb_inplace_true_divide*/
710 proxy_index, /*nb_index*/
Mark Dickinson7abb6c02019-04-26 15:56:15 +0900711 proxy_matmul, /*nb_matrix_multiply*/
712 proxy_imatmul, /*nb_inplace_matrix_multiply*/
Fred Drake8844d522001-10-05 21:52:26 +0000713};
714
715static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000716 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000717 0, /*sq_concat*/
718 0, /*sq_repeat*/
719 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000720 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000721 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000723 (objobjproc)proxy_contains, /* sq_contains */
724};
725
726static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000727 (lenfunc)proxy_length, /*mp_length*/
728 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000729 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
730};
731
732
733PyTypeObject
734_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000735 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000736 "weakproxy",
737 sizeof(PyWeakReference),
738 0,
739 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000740 (destructor)proxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200741 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 0, /* tp_getattr */
743 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200744 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000745 (reprfunc)proxy_repr, /* tp_repr */
746 &proxy_as_number, /* tp_as_number */
747 &proxy_as_sequence, /* tp_as_sequence */
748 &proxy_as_mapping, /* tp_as_mapping */
749 0, /* tp_hash */
750 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000751 proxy_str, /* tp_str */
752 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000753 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000755 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000756 0, /* tp_doc */
757 (traverseproc)gc_traverse, /* tp_traverse */
758 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000759 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000760 0, /* tp_weaklistoffset */
761 (getiterfunc)proxy_iter, /* tp_iter */
762 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000764};
765
766
767PyTypeObject
768_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000769 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000770 "weakcallableproxy",
771 sizeof(PyWeakReference),
772 0,
773 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000774 (destructor)proxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200775 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000776 0, /* tp_getattr */
777 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200778 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000779 (unaryfunc)proxy_repr, /* tp_repr */
780 &proxy_as_number, /* tp_as_number */
781 &proxy_as_sequence, /* tp_as_sequence */
782 &proxy_as_mapping, /* tp_as_mapping */
783 0, /* tp_hash */
784 proxy_call, /* tp_call */
785 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000786 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000787 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000788 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000789 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000790 0, /* tp_doc */
791 (traverseproc)gc_traverse, /* tp_traverse */
792 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000793 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000794 0, /* tp_weaklistoffset */
795 (getiterfunc)proxy_iter, /* tp_iter */
796 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000797};
798
799
Fred Drake8844d522001-10-05 21:52:26 +0000800
801PyObject *
802PyWeakref_NewRef(PyObject *ob, PyObject *callback)
803{
804 PyWeakReference *result = NULL;
805 PyWeakReference **list;
806 PyWeakReference *ref, *proxy;
807
Christian Heimes90aa7642007-12-19 02:45:37 +0000808 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000809 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000810 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000811 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000812 return NULL;
813 }
814 list = GET_WEAKREFS_LISTPTR(ob);
815 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000816 if (callback == Py_None)
817 callback = NULL;
818 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000819 /* return existing weak reference if it exists */
820 result = ref;
821 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000822 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000823 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000824 /* Note: new_weakref() can trigger cyclic GC, so the weakref
825 list on ob can be mutated. This means that the ref and
826 proxy pointers we got back earlier may have been collected,
827 so we need to compute these values again before we use
828 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000829 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000830 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000831 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000832 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000833 if (ref == NULL)
834 insert_head(result, list);
835 else {
836 /* Someone else added a ref without a callback
837 during GC. Return that one instead of this one
838 to avoid violating the invariants of the list
839 of weakrefs for ob. */
840 Py_DECREF(result);
841 Py_INCREF(ref);
842 result = ref;
843 }
Fred Drake8844d522001-10-05 21:52:26 +0000844 }
845 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000846 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000847
Fred Drakebc875f52004-02-04 23:14:14 +0000848 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000849 if (prev == NULL)
850 insert_head(result, list);
851 else
852 insert_after(result, prev);
853 }
Fred Drake8844d522001-10-05 21:52:26 +0000854 }
855 }
856 return (PyObject *) result;
857}
858
859
860PyObject *
861PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
862{
863 PyWeakReference *result = NULL;
864 PyWeakReference **list;
865 PyWeakReference *ref, *proxy;
866
Christian Heimes90aa7642007-12-19 02:45:37 +0000867 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000868 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000869 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000870 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000871 return NULL;
872 }
873 list = GET_WEAKREFS_LISTPTR(ob);
874 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000875 if (callback == Py_None)
876 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000877 if (callback == NULL)
878 /* attempt to return an existing weak reference if it exists */
879 result = proxy;
880 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000881 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000882 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000883 /* Note: new_weakref() can trigger cyclic GC, so the weakref
884 list on ob can be mutated. This means that the ref and
885 proxy pointers we got back earlier may have been collected,
886 so we need to compute these values again before we use
887 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000888 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000889 if (result != NULL) {
890 PyWeakReference *prev;
891
Victor Stinnerd2ec81a2020-02-07 09:17:07 +0100892 if (PyCallable_Check(ob)) {
893 Py_SET_TYPE(result, &_PyWeakref_CallableProxyType);
894 }
895 else {
896 Py_SET_TYPE(result, &_PyWeakref_ProxyType);
897 }
Fred Drakebc875f52004-02-04 23:14:14 +0000898 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000899 if (callback == NULL) {
900 if (proxy != NULL) {
901 /* Someone else added a proxy without a callback
902 during GC. Return that one instead of this one
903 to avoid violating the invariants of the list
904 of weakrefs for ob. */
905 Py_DECREF(result);
Victor Stinnerb37672d2018-11-22 03:37:50 +0100906 result = proxy;
907 Py_INCREF(result);
Fred Drake6d3265d2004-08-03 14:47:25 +0000908 goto skip_insert;
909 }
Fred Drake8844d522001-10-05 21:52:26 +0000910 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000911 }
Fred Drake8844d522001-10-05 21:52:26 +0000912 else
913 prev = (proxy == NULL) ? ref : proxy;
914
915 if (prev == NULL)
916 insert_head(result, list);
917 else
918 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000919 skip_insert:
920 ;
Fred Drake8844d522001-10-05 21:52:26 +0000921 }
922 }
923 return (PyObject *) result;
924}
925
926
927PyObject *
928PyWeakref_GetObject(PyObject *ref)
929{
930 if (ref == NULL || !PyWeakref_Check(ref)) {
931 PyErr_BadInternalCall();
932 return NULL;
933 }
934 return PyWeakref_GET_OBJECT(ref);
935}
936
Tim Petersead8b7a2004-10-30 23:09:22 +0000937/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
938 * handle_weakrefs().
939 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000940static void
941handle_callback(PyWeakReference *ref, PyObject *callback)
942{
Petr Viktorinffd97532020-02-11 17:46:57 +0100943 PyObject *cbresult = PyObject_CallOneArg(callback, (PyObject *)ref);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000944
945 if (cbresult == NULL)
946 PyErr_WriteUnraisable(callback);
947 else
948 Py_DECREF(cbresult);
949}
950
951/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000952 *
953 * This iterates through the weak references for 'object' and calls callbacks
954 * for those references which have one. It returns when all callbacks have
955 * been attempted.
956 */
957void
958PyObject_ClearWeakRefs(PyObject *object)
959{
960 PyWeakReference **list;
961
962 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000963 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Victor Stinnera93c51e2020-02-07 00:38:59 +0100964 || Py_REFCNT(object) != 0)
965 {
Fred Drake8844d522001-10-05 21:52:26 +0000966 PyErr_BadInternalCall();
967 return;
968 }
969 list = GET_WEAKREFS_LISTPTR(object);
970 /* Remove the callback-less basic and proxy references */
971 if (*list != NULL && (*list)->wr_callback == NULL) {
972 clear_weakref(*list);
973 if (*list != NULL && (*list)->wr_callback == NULL)
974 clear_weakref(*list);
975 }
976 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000977 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000978 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000979 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000980
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300981 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000982 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000983 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000984
Fred Drakeef8ebd12001-12-10 23:44:54 +0000985 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000986 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000987 if (callback != NULL) {
Victor Stinnera93c51e2020-02-07 00:38:59 +0100988 if (Py_REFCNT((PyObject *)current) > 0) {
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000989 handle_callback(current, callback);
Victor Stinnera93c51e2020-02-07 00:38:59 +0100990 }
Fred Drake0a4dd392004-07-02 18:57:45 +0000991 Py_DECREF(callback);
992 }
Fred Drake8844d522001-10-05 21:52:26 +0000993 }
994 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000995 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000996 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000997
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000998 tuple = PyTuple_New(count * 2);
999 if (tuple == NULL) {
Serhiy Storchaka4aa86792015-03-30 09:52:29 +03001000 _PyErr_ChainExceptions(err_type, err_value, err_tb);
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +00001001 return;
1002 }
Fred Drake8844d522001-10-05 21:52:26 +00001003
1004 for (i = 0; i < count; ++i) {
1005 PyWeakReference *next = current->wr_next;
1006
Victor Stinnera93c51e2020-02-07 00:38:59 +01001007 if (Py_REFCNT((PyObject *)current) > 0) {
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +00001008 Py_INCREF(current);
1009 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
1010 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
1011 }
1012 else {
1013 Py_DECREF(current->wr_callback);
1014 }
Fred Drake8844d522001-10-05 21:52:26 +00001015 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +00001016 clear_weakref(current);
1017 current = next;
1018 }
1019 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +00001020 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +00001021
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +00001022 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +00001023 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +00001024 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
1025 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +00001026 }
Fred Drake8844d522001-10-05 21:52:26 +00001027 }
1028 Py_DECREF(tuple);
1029 }
Serhiy Storchaka4aa86792015-03-30 09:52:29 +03001030 assert(!PyErr_Occurred());
1031 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +00001032 }
1033}