blob: 1e6697b729c9c0856b8b9e5f133417e17f023312 [file] [log] [blame]
Fred Drake8844d522001-10-05 21:52:26 +00001#include "Python.h"
Victor Stinner38aefc52020-04-06 14:07:02 +02002#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR
Fred Drake8844d522001-10-05 21:52:26 +00003#include "structmember.h"
4
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
Fred Drake8844d522001-10-05 21:52:26 +0000365PyTypeObject
366_PyWeakref_RefType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000367 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000368 "weakref",
369 sizeof(PyWeakReference),
370 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000371 weakref_dealloc, /*tp_dealloc*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200372 0, /*tp_vectorcall_offset*/
Fred Drake8844d522001-10-05 21:52:26 +0000373 0, /*tp_getattr*/
374 0, /*tp_setattr*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200375 0, /*tp_as_async*/
Fred Drake8844d522001-10-05 21:52:26 +0000376 (reprfunc)weakref_repr, /*tp_repr*/
377 0, /*tp_as_number*/
378 0, /*tp_as_sequence*/
379 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000380 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000381 (ternaryfunc)weakref_call, /*tp_call*/
382 0, /*tp_str*/
383 0, /*tp_getattro*/
384 0, /*tp_setattro*/
385 0, /*tp_as_buffer*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000386 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000387 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000388 0, /*tp_doc*/
389 (traverseproc)gc_traverse, /*tp_traverse*/
390 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000392 0, /*tp_weaklistoffset*/
393 0, /*tp_iter*/
394 0, /*tp_iternext*/
395 0, /*tp_methods*/
Mark Dickinson556e94b2013-04-13 15:45:44 +0100396 weakref_members, /*tp_members*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000397 0, /*tp_getset*/
398 0, /*tp_base*/
399 0, /*tp_dict*/
400 0, /*tp_descr_get*/
401 0, /*tp_descr_set*/
402 0, /*tp_dictoffset*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000403 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000404 PyType_GenericAlloc, /*tp_alloc*/
405 weakref___new__, /*tp_new*/
406 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000407};
408
409
410static int
411proxy_checkref(PyWeakReference *proxy)
412{
413 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
414 PyErr_SetString(PyExc_ReferenceError,
415 "weakly-referenced object no longer exists");
416 return 0;
417 }
418 return 1;
419}
420
421
Fred Drake73006d02001-10-18 18:04:18 +0000422/* If a parameter is a proxy, check that it is still "live" and wrap it,
423 * replacing the original value with the raw object. Raises ReferenceError
424 * if the param is a dead proxy.
425 */
426#define UNWRAP(o) \
427 if (PyWeakref_CheckProxy(o)) { \
428 if (!proxy_checkref((PyWeakReference *)o)) \
429 return NULL; \
430 o = PyWeakref_GET_OBJECT(o); \
431 }
432
Fred Drake8844d522001-10-05 21:52:26 +0000433#define WRAP_UNARY(method, generic) \
434 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000435 method(PyObject *proxy) { \
436 UNWRAP(proxy); \
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100437 Py_INCREF(proxy); \
438 PyObject* res = generic(proxy); \
439 Py_DECREF(proxy); \
440 return res; \
Fred Drake8844d522001-10-05 21:52:26 +0000441 }
442
443#define WRAP_BINARY(method, generic) \
444 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000445 method(PyObject *x, PyObject *y) { \
446 UNWRAP(x); \
447 UNWRAP(y); \
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100448 Py_INCREF(x); \
449 Py_INCREF(y); \
450 PyObject* res = generic(x, y); \
451 Py_DECREF(x); \
452 Py_DECREF(y); \
453 return res; \
Fred Drake8844d522001-10-05 21:52:26 +0000454 }
455
Fred Drake31f4d1f2001-10-18 19:21:46 +0000456/* Note that the third arg needs to be checked for NULL since the tp_call
457 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000458 */
Fred Drake8844d522001-10-05 21:52:26 +0000459#define WRAP_TERNARY(method, generic) \
460 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000461 method(PyObject *proxy, PyObject *v, PyObject *w) { \
462 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000463 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000464 if (w != NULL) \
465 UNWRAP(w); \
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100466 Py_INCREF(proxy); \
467 Py_INCREF(v); \
468 Py_XINCREF(w); \
469 PyObject* res = generic(proxy, v, w); \
470 Py_DECREF(proxy); \
471 Py_DECREF(v); \
472 Py_XDECREF(w); \
473 return res; \
Fred Drake8844d522001-10-05 21:52:26 +0000474 }
475
Benjamin Peterson32019772009-11-19 03:08:32 +0000476#define WRAP_METHOD(method, special) \
477 static PyObject * \
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530478 method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200479 _Py_IDENTIFIER(special); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000480 UNWRAP(proxy); \
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100481 Py_INCREF(proxy); \
482 PyObject* res = _PyObject_CallMethodIdNoArgs(proxy, &PyId_##special); \
483 Py_DECREF(proxy); \
484 return res; \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485 }
Benjamin Peterson32019772009-11-19 03:08:32 +0000486
Fred Drake8844d522001-10-05 21:52:26 +0000487
488/* direct slots */
489
490WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
491WRAP_UNARY(proxy_str, PyObject_Str)
INADA Naoki72dccde2017-02-16 09:26:01 +0900492WRAP_TERNARY(proxy_call, PyObject_Call)
Fred Drake8844d522001-10-05 21:52:26 +0000493
Fred Drake8844d522001-10-05 21:52:26 +0000494static PyObject *
495proxy_repr(PyWeakReference *proxy)
496{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100497 return PyUnicode_FromFormat(
498 "<weakproxy at %p to %s at %p>",
499 proxy,
500 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
501 PyWeakref_GET_OBJECT(proxy));
Fred Drake8844d522001-10-05 21:52:26 +0000502}
503
504
505static int
506proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
507{
508 if (!proxy_checkref(proxy))
509 return -1;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100510 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
511 Py_INCREF(obj);
512 int res = PyObject_SetAttr(obj, name, value);
513 Py_DECREF(obj);
514 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000515}
516
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000517static PyObject *
518proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000519{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000520 UNWRAP(proxy);
521 UNWRAP(v);
522 return PyObject_RichCompare(proxy, v, op);
Fred Drake8844d522001-10-05 21:52:26 +0000523}
524
525/* number slots */
526WRAP_BINARY(proxy_add, PyNumber_Add)
527WRAP_BINARY(proxy_sub, PyNumber_Subtract)
528WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000529WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
530WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000531WRAP_BINARY(proxy_mod, PyNumber_Remainder)
532WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
533WRAP_TERNARY(proxy_pow, PyNumber_Power)
534WRAP_UNARY(proxy_neg, PyNumber_Negative)
535WRAP_UNARY(proxy_pos, PyNumber_Positive)
536WRAP_UNARY(proxy_abs, PyNumber_Absolute)
537WRAP_UNARY(proxy_invert, PyNumber_Invert)
538WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
539WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
540WRAP_BINARY(proxy_and, PyNumber_And)
541WRAP_BINARY(proxy_xor, PyNumber_Xor)
542WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000543WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000544WRAP_UNARY(proxy_float, PyNumber_Float)
545WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
546WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
547WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000548WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
549WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000550WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
551WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
552WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
553WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
554WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
555WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
556WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000557WRAP_UNARY(proxy_index, PyNumber_Index)
Mark Dickinson7abb6c02019-04-26 15:56:15 +0900558WRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply)
559WRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply)
Fred Drake8844d522001-10-05 21:52:26 +0000560
Tim Peters403a2032003-11-20 21:21:46 +0000561static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000562proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000563{
564 PyObject *o = PyWeakref_GET_OBJECT(proxy);
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100565 if (!proxy_checkref(proxy)) {
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000566 return -1;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100567 }
568 Py_INCREF(o);
569 int res = PyObject_IsTrue(o);
570 Py_DECREF(o);
571 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000572}
573
Fred Drake0a4dd392004-07-02 18:57:45 +0000574static void
575proxy_dealloc(PyWeakReference *self)
576{
577 if (self->wr_callback != NULL)
578 PyObject_GC_UnTrack((PyObject *)self);
579 clear_weakref(self);
580 PyObject_GC_Del(self);
581}
582
Fred Drake8844d522001-10-05 21:52:26 +0000583/* sequence slots */
584
Fred Drake8844d522001-10-05 21:52:26 +0000585static int
586proxy_contains(PyWeakReference *proxy, PyObject *value)
587{
588 if (!proxy_checkref(proxy))
589 return -1;
Fred Drake8844d522001-10-05 21:52:26 +0000590
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100591 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
592 Py_INCREF(obj);
593 int res = PySequence_Contains(obj, value);
594 Py_DECREF(obj);
595 return res;
596}
Fred Drake8844d522001-10-05 21:52:26 +0000597
598/* mapping slots */
599
Martin v. Löwis18e16552006-02-15 17:27:45 +0000600static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000601proxy_length(PyWeakReference *proxy)
602{
603 if (!proxy_checkref(proxy))
604 return -1;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100605
606 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
607 Py_INCREF(obj);
608 Py_ssize_t res = PyObject_Length(obj);
609 Py_DECREF(obj);
610 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000611}
612
613WRAP_BINARY(proxy_getitem, PyObject_GetItem)
614
615static int
616proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
617{
618 if (!proxy_checkref(proxy))
619 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000620
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100621 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
622 Py_INCREF(obj);
623 int res;
624 if (value == NULL) {
625 res = PyObject_DelItem(obj, key);
626 } else {
627 res = PyObject_SetItem(obj, key, value);
628 }
629 Py_DECREF(obj);
630 return res;
Fred Drake8844d522001-10-05 21:52:26 +0000631}
632
Fred Drakef16c3dc2002-08-09 18:34:16 +0000633/* iterator slots */
634
635static PyObject *
636proxy_iter(PyWeakReference *proxy)
637{
638 if (!proxy_checkref(proxy))
639 return NULL;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100640 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
641 Py_INCREF(obj);
642 PyObject* res = PyObject_GetIter(obj);
643 Py_DECREF(obj);
644 return res;
Fred Drakef16c3dc2002-08-09 18:34:16 +0000645}
646
647static PyObject *
648proxy_iternext(PyWeakReference *proxy)
649{
650 if (!proxy_checkref(proxy))
651 return NULL;
Pablo Galindo10cd00a2019-10-08 16:30:50 +0100652
653 PyObject *obj = PyWeakref_GET_OBJECT(proxy);
654 Py_INCREF(obj);
655 PyObject* res = PyIter_Next(obj);
656 Py_DECREF(obj);
657 return res;
Fred Drakef16c3dc2002-08-09 18:34:16 +0000658}
659
Fred Drake8844d522001-10-05 21:52:26 +0000660
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200661WRAP_METHOD(proxy_bytes, __bytes__)
Benjamin Peterson32019772009-11-19 03:08:32 +0000662
663
664static PyMethodDef proxy_methods[] = {
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530665 {"__bytes__", proxy_bytes, METH_NOARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000667};
668
669
Fred Drake8844d522001-10-05 21:52:26 +0000670static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000671 proxy_add, /*nb_add*/
672 proxy_sub, /*nb_subtract*/
673 proxy_mul, /*nb_multiply*/
674 proxy_mod, /*nb_remainder*/
675 proxy_divmod, /*nb_divmod*/
676 proxy_pow, /*nb_power*/
677 proxy_neg, /*nb_negative*/
678 proxy_pos, /*nb_positive*/
679 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000680 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000681 proxy_invert, /*nb_invert*/
682 proxy_lshift, /*nb_lshift*/
683 proxy_rshift, /*nb_rshift*/
684 proxy_and, /*nb_and*/
685 proxy_xor, /*nb_xor*/
686 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000687 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000688 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000689 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000690 proxy_iadd, /*nb_inplace_add*/
691 proxy_isub, /*nb_inplace_subtract*/
692 proxy_imul, /*nb_inplace_multiply*/
693 proxy_imod, /*nb_inplace_remainder*/
694 proxy_ipow, /*nb_inplace_power*/
695 proxy_ilshift, /*nb_inplace_lshift*/
696 proxy_irshift, /*nb_inplace_rshift*/
697 proxy_iand, /*nb_inplace_and*/
698 proxy_ixor, /*nb_inplace_xor*/
699 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000700 proxy_floor_div, /*nb_floor_divide*/
701 proxy_true_div, /*nb_true_divide*/
702 proxy_ifloor_div, /*nb_inplace_floor_divide*/
703 proxy_itrue_div, /*nb_inplace_true_divide*/
704 proxy_index, /*nb_index*/
Mark Dickinson7abb6c02019-04-26 15:56:15 +0900705 proxy_matmul, /*nb_matrix_multiply*/
706 proxy_imatmul, /*nb_inplace_matrix_multiply*/
Fred Drake8844d522001-10-05 21:52:26 +0000707};
708
709static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000710 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000711 0, /*sq_concat*/
712 0, /*sq_repeat*/
713 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000714 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000715 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000716 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000717 (objobjproc)proxy_contains, /* sq_contains */
718};
719
720static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000721 (lenfunc)proxy_length, /*mp_length*/
722 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000723 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
724};
725
726
727PyTypeObject
728_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000729 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000730 "weakproxy",
731 sizeof(PyWeakReference),
732 0,
733 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000734 (destructor)proxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200735 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 0, /* tp_getattr */
737 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200738 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000739 (reprfunc)proxy_repr, /* tp_repr */
740 &proxy_as_number, /* tp_as_number */
741 &proxy_as_sequence, /* tp_as_sequence */
742 &proxy_as_mapping, /* tp_as_mapping */
743 0, /* tp_hash */
744 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000745 proxy_str, /* tp_str */
746 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000747 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000749 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000750 0, /* tp_doc */
751 (traverseproc)gc_traverse, /* tp_traverse */
752 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000753 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000754 0, /* tp_weaklistoffset */
755 (getiterfunc)proxy_iter, /* tp_iter */
756 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000758};
759
760
761PyTypeObject
762_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000763 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000764 "weakcallableproxy",
765 sizeof(PyWeakReference),
766 0,
767 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000768 (destructor)proxy_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200769 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 0, /* tp_getattr */
771 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200772 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000773 (unaryfunc)proxy_repr, /* tp_repr */
774 &proxy_as_number, /* tp_as_number */
775 &proxy_as_sequence, /* tp_as_sequence */
776 &proxy_as_mapping, /* tp_as_mapping */
777 0, /* tp_hash */
778 proxy_call, /* tp_call */
779 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000780 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000781 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000783 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000784 0, /* tp_doc */
785 (traverseproc)gc_traverse, /* tp_traverse */
786 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000787 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000788 0, /* tp_weaklistoffset */
789 (getiterfunc)proxy_iter, /* tp_iter */
790 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000791};
792
793
Fred Drake8844d522001-10-05 21:52:26 +0000794
795PyObject *
796PyWeakref_NewRef(PyObject *ob, PyObject *callback)
797{
798 PyWeakReference *result = NULL;
799 PyWeakReference **list;
800 PyWeakReference *ref, *proxy;
801
Christian Heimes90aa7642007-12-19 02:45:37 +0000802 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000803 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000804 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000805 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000806 return NULL;
807 }
808 list = GET_WEAKREFS_LISTPTR(ob);
809 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000810 if (callback == Py_None)
811 callback = NULL;
812 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000813 /* return existing weak reference if it exists */
814 result = ref;
815 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000816 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000817 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000818 /* Note: new_weakref() can trigger cyclic GC, so the weakref
819 list on ob can be mutated. This means that the ref and
820 proxy pointers we got back earlier may have been collected,
821 so we need to compute these values again before we use
822 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000823 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000824 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000825 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000826 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000827 if (ref == NULL)
828 insert_head(result, list);
829 else {
830 /* Someone else added a ref without a callback
831 during GC. Return that one instead of this one
832 to avoid violating the invariants of the list
833 of weakrefs for ob. */
834 Py_DECREF(result);
835 Py_INCREF(ref);
836 result = ref;
837 }
Fred Drake8844d522001-10-05 21:52:26 +0000838 }
839 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000840 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000841
Fred Drakebc875f52004-02-04 23:14:14 +0000842 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000843 if (prev == NULL)
844 insert_head(result, list);
845 else
846 insert_after(result, prev);
847 }
Fred Drake8844d522001-10-05 21:52:26 +0000848 }
849 }
850 return (PyObject *) result;
851}
852
853
854PyObject *
855PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
856{
857 PyWeakReference *result = NULL;
858 PyWeakReference **list;
859 PyWeakReference *ref, *proxy;
860
Christian Heimes90aa7642007-12-19 02:45:37 +0000861 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000862 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000863 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000864 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000865 return NULL;
866 }
867 list = GET_WEAKREFS_LISTPTR(ob);
868 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000869 if (callback == Py_None)
870 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000871 if (callback == NULL)
872 /* attempt to return an existing weak reference if it exists */
873 result = proxy;
874 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000875 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000876 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000877 /* Note: new_weakref() can trigger cyclic GC, so the weakref
878 list on ob can be mutated. This means that the ref and
879 proxy pointers we got back earlier may have been collected,
880 so we need to compute these values again before we use
881 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000882 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000883 if (result != NULL) {
884 PyWeakReference *prev;
885
Victor Stinnerd2ec81a2020-02-07 09:17:07 +0100886 if (PyCallable_Check(ob)) {
887 Py_SET_TYPE(result, &_PyWeakref_CallableProxyType);
888 }
889 else {
890 Py_SET_TYPE(result, &_PyWeakref_ProxyType);
891 }
Fred Drakebc875f52004-02-04 23:14:14 +0000892 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000893 if (callback == NULL) {
894 if (proxy != NULL) {
895 /* Someone else added a proxy without a callback
896 during GC. Return that one instead of this one
897 to avoid violating the invariants of the list
898 of weakrefs for ob. */
899 Py_DECREF(result);
Victor Stinnerb37672d2018-11-22 03:37:50 +0100900 result = proxy;
901 Py_INCREF(result);
Fred Drake6d3265d2004-08-03 14:47:25 +0000902 goto skip_insert;
903 }
Fred Drake8844d522001-10-05 21:52:26 +0000904 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000905 }
Fred Drake8844d522001-10-05 21:52:26 +0000906 else
907 prev = (proxy == NULL) ? ref : proxy;
908
909 if (prev == NULL)
910 insert_head(result, list);
911 else
912 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000913 skip_insert:
914 ;
Fred Drake8844d522001-10-05 21:52:26 +0000915 }
916 }
917 return (PyObject *) result;
918}
919
920
921PyObject *
922PyWeakref_GetObject(PyObject *ref)
923{
924 if (ref == NULL || !PyWeakref_Check(ref)) {
925 PyErr_BadInternalCall();
926 return NULL;
927 }
928 return PyWeakref_GET_OBJECT(ref);
929}
930
Tim Petersead8b7a2004-10-30 23:09:22 +0000931/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
932 * handle_weakrefs().
933 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000934static void
935handle_callback(PyWeakReference *ref, PyObject *callback)
936{
Petr Viktorinffd97532020-02-11 17:46:57 +0100937 PyObject *cbresult = PyObject_CallOneArg(callback, (PyObject *)ref);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000938
939 if (cbresult == NULL)
940 PyErr_WriteUnraisable(callback);
941 else
942 Py_DECREF(cbresult);
943}
944
945/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000946 *
947 * This iterates through the weak references for 'object' and calls callbacks
948 * for those references which have one. It returns when all callbacks have
949 * been attempted.
950 */
951void
952PyObject_ClearWeakRefs(PyObject *object)
953{
954 PyWeakReference **list;
955
956 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000957 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Victor Stinnera93c51e2020-02-07 00:38:59 +0100958 || Py_REFCNT(object) != 0)
959 {
Fred Drake8844d522001-10-05 21:52:26 +0000960 PyErr_BadInternalCall();
961 return;
962 }
963 list = GET_WEAKREFS_LISTPTR(object);
964 /* Remove the callback-less basic and proxy references */
965 if (*list != NULL && (*list)->wr_callback == NULL) {
966 clear_weakref(*list);
967 if (*list != NULL && (*list)->wr_callback == NULL)
968 clear_weakref(*list);
969 }
970 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000971 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000972 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000973 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000974
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300975 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000976 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000977 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000978
Fred Drakeef8ebd12001-12-10 23:44:54 +0000979 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000980 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000981 if (callback != NULL) {
Victor Stinnera93c51e2020-02-07 00:38:59 +0100982 if (Py_REFCNT((PyObject *)current) > 0) {
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000983 handle_callback(current, callback);
Victor Stinnera93c51e2020-02-07 00:38:59 +0100984 }
Fred Drake0a4dd392004-07-02 18:57:45 +0000985 Py_DECREF(callback);
986 }
Fred Drake8844d522001-10-05 21:52:26 +0000987 }
988 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000989 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000990 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000991
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000992 tuple = PyTuple_New(count * 2);
993 if (tuple == NULL) {
Serhiy Storchaka4aa86792015-03-30 09:52:29 +0300994 _PyErr_ChainExceptions(err_type, err_value, err_tb);
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000995 return;
996 }
Fred Drake8844d522001-10-05 21:52:26 +0000997
998 for (i = 0; i < count; ++i) {
999 PyWeakReference *next = current->wr_next;
1000
Victor Stinnera93c51e2020-02-07 00:38:59 +01001001 if (Py_REFCNT((PyObject *)current) > 0) {
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +00001002 Py_INCREF(current);
1003 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
1004 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
1005 }
1006 else {
1007 Py_DECREF(current->wr_callback);
1008 }
Fred Drake8844d522001-10-05 21:52:26 +00001009 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +00001010 clear_weakref(current);
1011 current = next;
1012 }
1013 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +00001014 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +00001015
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +00001016 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +00001017 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +00001018 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
1019 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +00001020 }
Fred Drake8844d522001-10-05 21:52:26 +00001021 }
1022 Py_DECREF(tuple);
1023 }
Serhiy Storchaka4aa86792015-03-30 09:52:29 +03001024 assert(!PyErr_Occurred());
1025 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +00001026 }
1027}