/src/Python-3.8.3/Objects/weakrefobject.c
Line  | Count  | Source  | 
1  |  | #include "Python.h"  | 
2  |  | #include "structmember.h"  | 
3  |  |  | 
4  |  |  | 
5  |  | #define GET_WEAKREFS_LISTPTR(o) \  | 
6  | 9.75k  |         ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))  | 
7  |  |  | 
8  |  |  | 
9  |  | Py_ssize_t  | 
10  |  | _PyWeakref_GetWeakrefCount(PyWeakReference *head)  | 
11  | 362  | { | 
12  | 362  |     Py_ssize_t count = 0;  | 
13  |  |  | 
14  | 724  |     while (head != NULL) { | 
15  | 362  |         ++count;  | 
16  | 362  |         head = head->wr_next;  | 
17  | 362  |     }  | 
18  | 362  |     return count;  | 
19  | 362  | }  | 
20  |  |  | 
21  |  |  | 
22  |  | static void  | 
23  |  | init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)  | 
24  | 6.18k  | { | 
25  | 6.18k  |     self->hash = -1;  | 
26  | 6.18k  |     self->wr_object = ob;  | 
27  | 6.18k  |     self->wr_prev = NULL;  | 
28  | 6.18k  |     self->wr_next = NULL;  | 
29  | 6.18k  |     Py_XINCREF(callback);  | 
30  | 6.18k  |     self->wr_callback = callback;  | 
31  | 6.18k  | }  | 
32  |  |  | 
33  |  | static PyWeakReference *  | 
34  |  | new_weakref(PyObject *ob, PyObject *callback)  | 
35  | 5.81k  | { | 
36  | 5.81k  |     PyWeakReference *result;  | 
37  |  |  | 
38  | 5.81k  |     result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);  | 
39  | 5.81k  |     if (result) { | 
40  | 5.81k  |         init_weakref(result, ob, callback);  | 
41  | 5.81k  |         PyObject_GC_Track(result);  | 
42  | 5.81k  |     }  | 
43  | 5.81k  |     return result;  | 
44  | 5.81k  | }  | 
45  |  |  | 
46  |  |  | 
47  |  | /* This function clears the passed-in reference and removes it from the  | 
48  |  |  * list of weak references for the referent.  This is the only code that  | 
49  |  |  * removes an item from the doubly-linked list of weak references for an  | 
50  |  |  * object; it is also responsible for clearing the callback slot.  | 
51  |  |  */  | 
52  |  | static void  | 
53  |  | clear_weakref(PyWeakReference *self)  | 
54  | 1.14k  | { | 
55  | 1.14k  |     PyObject *callback = self->wr_callback;  | 
56  |  |  | 
57  | 1.14k  |     if (self->wr_object != Py_None) { | 
58  | 780  |         PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);  | 
59  |  |  | 
60  | 780  |         if (*list == self)  | 
61  |  |             /* If 'self' is the end of the list (and thus self->wr_next == NULL)  | 
62  |  |                then the weakref list itself (and thus the value of *list) will  | 
63  |  |                end up being set to NULL. */  | 
64  | 637  |             *list = self->wr_next;  | 
65  | 780  |         self->wr_object = Py_None;  | 
66  | 780  |         if (self->wr_prev != NULL)  | 
67  | 143  |             self->wr_prev->wr_next = self->wr_next;  | 
68  | 780  |         if (self->wr_next != NULL)  | 
69  | 1  |             self->wr_next->wr_prev = self->wr_prev;  | 
70  | 780  |         self->wr_prev = NULL;  | 
71  | 780  |         self->wr_next = NULL;  | 
72  | 780  |     }  | 
73  | 1.14k  |     if (callback != NULL) { | 
74  | 143  |         Py_DECREF(callback);  | 
75  | 143  |         self->wr_callback = NULL;  | 
76  | 143  |     }  | 
77  | 1.14k  | }  | 
78  |  |  | 
79  |  | /* Cyclic gc uses this to *just* clear the passed-in reference, leaving  | 
80  |  |  * the callback intact and uncalled.  It must be possible to call self's  | 
81  |  |  * tp_dealloc() after calling this, so self has to be left in a sane enough  | 
82  |  |  * state for that to work.  We expect tp_dealloc to decref the callback  | 
83  |  |  * then.  The reason for not letting clear_weakref() decref the callback  | 
84  |  |  * right now is that if the callback goes away, that may in turn trigger  | 
85  |  |  * another callback (if a weak reference to the callback exists) -- running  | 
86  |  |  * arbitrary Python code in the middle of gc is a disaster.  The convolution  | 
87  |  |  * here allows gc to delay triggering such callbacks until the world is in  | 
88  |  |  * a sane state again.  | 
89  |  |  */  | 
90  |  | void  | 
91  |  | _PyWeakref_ClearRef(PyWeakReference *self)  | 
92  | 6  | { | 
93  | 6  |     PyObject *callback;  | 
94  |  |  | 
95  | 6  |     assert(self != NULL);  | 
96  | 6  |     assert(PyWeakref_Check(self));  | 
97  |  |     /* Preserve and restore the callback around clear_weakref. */  | 
98  | 6  |     callback = self->wr_callback;  | 
99  | 6  |     self->wr_callback = NULL;  | 
100  | 6  |     clear_weakref(self);  | 
101  | 6  |     self->wr_callback = callback;  | 
102  | 6  | }  | 
103  |  |  | 
104  |  | static void  | 
105  |  | weakref_dealloc(PyObject *self)  | 
106  | 780  | { | 
107  | 780  |     PyObject_GC_UnTrack(self);  | 
108  | 780  |     clear_weakref((PyWeakReference *) self);  | 
109  | 780  |     Py_TYPE(self)->tp_free(self);  | 
110  | 780  | }  | 
111  |  |  | 
112  |  |  | 
113  |  | static int  | 
114  |  | gc_traverse(PyWeakReference *self, visitproc visit, void *arg)  | 
115  | 11.0k  | { | 
116  | 11.0k  |     Py_VISIT(self->wr_callback);  | 
117  | 11.0k  |     return 0;  | 
118  | 11.0k  | }  | 
119  |  |  | 
120  |  |  | 
121  |  | static int  | 
122  |  | gc_clear(PyWeakReference *self)  | 
123  | 0  | { | 
124  | 0  |     clear_weakref(self);  | 
125  | 0  |     return 0;  | 
126  | 0  | }  | 
127  |  |  | 
128  |  |  | 
129  |  | static PyObject *  | 
130  |  | weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)  | 
131  | 56  | { | 
132  | 56  |     static char *kwlist[] = {NULL}; | 
133  |  |  | 
134  | 56  |     if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) { | 
135  | 56  |         PyObject *object = PyWeakref_GET_OBJECT(self);  | 
136  | 56  |         Py_INCREF(object);  | 
137  | 56  |         return (object);  | 
138  | 56  |     }  | 
139  | 0  |     return NULL;  | 
140  | 56  | }  | 
141  |  |  | 
142  |  |  | 
143  |  | static Py_hash_t  | 
144  |  | weakref_hash(PyWeakReference *self)  | 
145  | 1.20k  | { | 
146  | 1.20k  |     if (self->hash != -1)  | 
147  | 29  |         return self->hash;  | 
148  | 1.17k  |     PyObject* obj = PyWeakref_GET_OBJECT(self);  | 
149  | 1.17k  |     if (obj == Py_None) { | 
150  | 0  |         PyErr_SetString(PyExc_TypeError, "weak object has gone away");  | 
151  | 0  |         return -1;  | 
152  | 0  |     }  | 
153  | 1.17k  |     Py_INCREF(obj);  | 
154  | 1.17k  |     self->hash = PyObject_Hash(obj);  | 
155  | 1.17k  |     Py_DECREF(obj);  | 
156  | 1.17k  |     return self->hash;  | 
157  | 1.17k  | }  | 
158  |  |  | 
159  |  |  | 
160  |  | static PyObject *  | 
161  |  | weakref_repr(PyWeakReference *self)  | 
162  | 0  | { | 
163  | 0  |     PyObject *name, *repr;  | 
164  | 0  |     _Py_IDENTIFIER(__name__);  | 
165  | 0  |     PyObject* obj = PyWeakref_GET_OBJECT(self);  | 
166  |  | 
  | 
167  | 0  |     if (obj == Py_None) { | 
168  | 0  |         return PyUnicode_FromFormat("<weakref at %p; dead>", self); | 
169  | 0  |     }  | 
170  |  |  | 
171  | 0  |     Py_INCREF(obj);  | 
172  | 0  |     if (_PyObject_LookupAttrId(obj, &PyId___name__, &name) < 0) { | 
173  | 0  |         Py_DECREF(obj);  | 
174  | 0  |         return NULL;  | 
175  | 0  |     }  | 
176  | 0  |     if (name == NULL || !PyUnicode_Check(name)) { | 
177  | 0  |         repr = PyUnicode_FromFormat(  | 
178  | 0  |             "<weakref at %p; to '%s' at %p>",  | 
179  | 0  |             self,  | 
180  | 0  |             Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,  | 
181  | 0  |             obj);  | 
182  | 0  |     }  | 
183  | 0  |     else { | 
184  | 0  |         repr = PyUnicode_FromFormat(  | 
185  | 0  |             "<weakref at %p; to '%s' at %p (%U)>",  | 
186  | 0  |             self,  | 
187  | 0  |             Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,  | 
188  | 0  |             obj,  | 
189  | 0  |             name);  | 
190  | 0  |     }  | 
191  | 0  |     Py_DECREF(obj);  | 
192  | 0  |     Py_XDECREF(name);  | 
193  | 0  |     return repr;  | 
194  | 0  | }  | 
195  |  |  | 
196  |  | /* Weak references only support equality, not ordering. Two weak references  | 
197  |  |    are equal if the underlying objects are equal. If the underlying object has  | 
198  |  |    gone away, they are equal if they are identical. */  | 
199  |  |  | 
200  |  | static PyObject *  | 
201  |  | weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)  | 
202  | 13  | { | 
203  | 13  |     if ((op != Py_EQ && op != Py_NE) ||  | 
204  | 13  |         !PyWeakref_Check(self) ||  | 
205  | 13  |         !PyWeakref_Check(other)) { | 
206  | 0  |         Py_RETURN_NOTIMPLEMENTED;  | 
207  | 0  |     }  | 
208  | 13  |     if (PyWeakref_GET_OBJECT(self) == Py_None  | 
209  | 13  |         || PyWeakref_GET_OBJECT(other) == Py_None) { | 
210  | 0  |         int res = (self == other);  | 
211  | 0  |         if (op == Py_NE)  | 
212  | 0  |             res = !res;  | 
213  | 0  |         if (res)  | 
214  | 0  |             Py_RETURN_TRUE;  | 
215  | 0  |         else  | 
216  | 0  |             Py_RETURN_FALSE;  | 
217  | 0  |     }  | 
218  | 13  |     PyObject* obj = PyWeakref_GET_OBJECT(self);  | 
219  | 13  |     PyObject* other_obj = PyWeakref_GET_OBJECT(other);  | 
220  | 13  |     Py_INCREF(obj);  | 
221  | 13  |     Py_INCREF(other_obj);  | 
222  | 13  |     PyObject* res = PyObject_RichCompare(obj, other_obj, op);  | 
223  | 13  |     Py_DECREF(obj);  | 
224  | 13  |     Py_DECREF(other_obj);  | 
225  | 13  |     return res;  | 
226  | 13  | }  | 
227  |  |  | 
228  |  | /* Given the head of an object's list of weak references, extract the  | 
229  |  |  * two callback-less refs (ref and proxy).  Used to determine if the  | 
230  |  |  * shared references exist and to determine the back link for newly  | 
231  |  |  * inserted references.  | 
232  |  |  */  | 
233  |  | static void  | 
234  |  | get_basic_refs(PyWeakReference *head,  | 
235  |  |                PyWeakReference **refp, PyWeakReference **proxyp)  | 
236  | 13.1k  | { | 
237  | 13.1k  |     *refp = NULL;  | 
238  | 13.1k  |     *proxyp = NULL;  | 
239  |  |  | 
240  | 13.1k  |     if (head != NULL && head->wr_callback == NULL) { | 
241  |  |         /* We need to be careful that the "basic refs" aren't  | 
242  |  |            subclasses of the main types.  That complicates this a  | 
243  |  |            little. */  | 
244  | 2.54k  |         if (PyWeakref_CheckRefExact(head)) { | 
245  | 2.54k  |             *refp = head;  | 
246  | 2.54k  |             head = head->wr_next;  | 
247  | 2.54k  |         }  | 
248  | 2.54k  |         if (head != NULL  | 
249  | 717  |             && head->wr_callback == NULL  | 
250  | 0  |             && PyWeakref_CheckProxy(head)) { | 
251  | 0  |             *proxyp = head;  | 
252  |  |             /* head = head->wr_next; */  | 
253  | 0  |         }  | 
254  | 2.54k  |     }  | 
255  | 13.1k  | }  | 
256  |  |  | 
257  |  | /* Insert 'newref' in the list after 'prev'.  Both must be non-NULL. */  | 
258  |  | static void  | 
259  |  | insert_after(PyWeakReference *newref, PyWeakReference *prev)  | 
260  | 877  | { | 
261  | 877  |     newref->wr_prev = prev;  | 
262  | 877  |     newref->wr_next = prev->wr_next;  | 
263  | 877  |     if (prev->wr_next != NULL)  | 
264  | 344  |         prev->wr_next->wr_prev = newref;  | 
265  | 877  |     prev->wr_next = newref;  | 
266  | 877  | }  | 
267  |  |  | 
268  |  | /* Insert 'newref' at the head of the list; 'list' points to the variable  | 
269  |  |  * that stores the head.  | 
270  |  |  */  | 
271  |  | static void  | 
272  |  | insert_head(PyWeakReference *newref, PyWeakReference **list)  | 
273  | 5.30k  | { | 
274  | 5.30k  |     PyWeakReference *next = *list;  | 
275  |  |  | 
276  | 5.30k  |     newref->wr_prev = NULL;  | 
277  | 5.30k  |     newref->wr_next = next;  | 
278  | 5.30k  |     if (next != NULL)  | 
279  | 2  |         next->wr_prev = newref;  | 
280  | 5.30k  |     *list = newref;  | 
281  | 5.30k  | }  | 
282  |  |  | 
283  |  | static int  | 
284  |  | parse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs,  | 
285  |  |                         PyObject **obp, PyObject **callbackp)  | 
286  | 740  | { | 
287  | 740  |     return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);  | 
288  | 740  | }  | 
289  |  |  | 
290  |  | static PyObject *  | 
291  |  | weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)  | 
292  | 370  | { | 
293  | 370  |     PyWeakReference *self = NULL;  | 
294  | 370  |     PyObject *ob, *callback = NULL;  | 
295  |  |  | 
296  | 370  |     if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) { | 
297  | 370  |         PyWeakReference *ref, *proxy;  | 
298  | 370  |         PyWeakReference **list;  | 
299  |  |  | 
300  | 370  |         if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { | 
301  | 0  |             PyErr_Format(PyExc_TypeError,  | 
302  | 0  |                          "cannot create weak reference to '%s' object",  | 
303  | 0  |                          Py_TYPE(ob)->tp_name);  | 
304  | 0  |             return NULL;  | 
305  | 0  |         }  | 
306  | 370  |         if (callback == Py_None)  | 
307  | 0  |             callback = NULL;  | 
308  | 370  |         list = GET_WEAKREFS_LISTPTR(ob);  | 
309  | 370  |         get_basic_refs(*list, &ref, &proxy);  | 
310  | 370  |         if (callback == NULL && type == &_PyWeakref_RefType) { | 
311  | 3  |             if (ref != NULL) { | 
312  |  |                 /* We can re-use an existing reference. */  | 
313  | 0  |                 Py_INCREF(ref);  | 
314  | 0  |                 return (PyObject *)ref;  | 
315  | 0  |             }  | 
316  | 3  |         }  | 
317  |  |         /* We have to create a new reference. */  | 
318  |  |         /* Note: the tp_alloc() can trigger cyclic GC, so the weakref  | 
319  |  |            list on ob can be mutated.  This means that the ref and  | 
320  |  |            proxy pointers we got back earlier may have been collected,  | 
321  |  |            so we need to compute these values again before we use  | 
322  |  |            them. */  | 
323  | 370  |         self = (PyWeakReference *) (type->tp_alloc(type, 0));  | 
324  | 370  |         if (self != NULL) { | 
325  | 370  |             init_weakref(self, ob, callback);  | 
326  | 370  |             if (callback == NULL && type == &_PyWeakref_RefType) { | 
327  | 3  |                 insert_head(self, list);  | 
328  | 3  |             }  | 
329  | 367  |             else { | 
330  | 367  |                 PyWeakReference *prev;  | 
331  |  |  | 
332  | 367  |                 get_basic_refs(*list, &ref, &proxy);  | 
333  | 367  |                 prev = (proxy == NULL) ? ref : proxy;  | 
334  | 367  |                 if (prev == NULL)  | 
335  | 367  |                     insert_head(self, list);  | 
336  | 0  |                 else  | 
337  | 0  |                     insert_after(self, prev);  | 
338  | 367  |             }  | 
339  | 370  |         }  | 
340  | 370  |     }  | 
341  | 370  |     return (PyObject *)self;  | 
342  | 370  | }  | 
343  |  |  | 
344  |  | static int  | 
345  |  | weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)  | 
346  | 370  | { | 
347  | 370  |     PyObject *tmp;  | 
348  |  |  | 
349  | 370  |     if (!_PyArg_NoKeywords("ref", kwargs)) | 
350  | 0  |         return -1;  | 
351  |  |  | 
352  | 370  |     if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp)) | 
353  | 370  |         return 0;  | 
354  | 0  |     else  | 
355  | 0  |         return -1;  | 
356  | 370  | }  | 
357  |  |  | 
358  |  |  | 
359  |  | static PyMemberDef weakref_members[] = { | 
360  |  |     {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY}, | 
361  |  |     {NULL} /* Sentinel */ | 
362  |  | };  | 
363  |  |  | 
364  |  | PyTypeObject  | 
365  |  | _PyWeakref_RefType = { | 
366  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0)  | 
367  |  |     "weakref",  | 
368  |  |     sizeof(PyWeakReference),  | 
369  |  |     0,  | 
370  |  |     weakref_dealloc,            /*tp_dealloc*/  | 
371  |  |     0,                          /*tp_vectorcall_offset*/  | 
372  |  |     0,                          /*tp_getattr*/  | 
373  |  |     0,                          /*tp_setattr*/  | 
374  |  |     0,                          /*tp_as_async*/  | 
375  |  |     (reprfunc)weakref_repr,     /*tp_repr*/  | 
376  |  |     0,                          /*tp_as_number*/  | 
377  |  |     0,                          /*tp_as_sequence*/  | 
378  |  |     0,                          /*tp_as_mapping*/  | 
379  |  |     (hashfunc)weakref_hash,     /*tp_hash*/  | 
380  |  |     (ternaryfunc)weakref_call,  /*tp_call*/  | 
381  |  |     0,                          /*tp_str*/  | 
382  |  |     0,                          /*tp_getattro*/  | 
383  |  |     0,                          /*tp_setattro*/  | 
384  |  |     0,                          /*tp_as_buffer*/  | 
385  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC  | 
386  |  |         | Py_TPFLAGS_BASETYPE,  /*tp_flags*/  | 
387  |  |     0,                          /*tp_doc*/  | 
388  |  |     (traverseproc)gc_traverse,  /*tp_traverse*/  | 
389  |  |     (inquiry)gc_clear,          /*tp_clear*/  | 
390  |  |     (richcmpfunc)weakref_richcompare,   /*tp_richcompare*/  | 
391  |  |     0,                          /*tp_weaklistoffset*/  | 
392  |  |     0,                          /*tp_iter*/  | 
393  |  |     0,                          /*tp_iternext*/  | 
394  |  |     0,                          /*tp_methods*/  | 
395  |  |     weakref_members,            /*tp_members*/  | 
396  |  |     0,                          /*tp_getset*/  | 
397  |  |     0,                          /*tp_base*/  | 
398  |  |     0,                          /*tp_dict*/  | 
399  |  |     0,                          /*tp_descr_get*/  | 
400  |  |     0,                          /*tp_descr_set*/  | 
401  |  |     0,                          /*tp_dictoffset*/  | 
402  |  |     weakref___init__,           /*tp_init*/  | 
403  |  |     PyType_GenericAlloc,        /*tp_alloc*/  | 
404  |  |     weakref___new__,            /*tp_new*/  | 
405  |  |     PyObject_GC_Del,            /*tp_free*/  | 
406  |  | };  | 
407  |  |  | 
408  |  |  | 
409  |  | static int  | 
410  |  | proxy_checkref(PyWeakReference *proxy)  | 
411  | 0  | { | 
412  | 0  |     if (PyWeakref_GET_OBJECT(proxy) == Py_None) { | 
413  | 0  |         PyErr_SetString(PyExc_ReferenceError,  | 
414  | 0  |                         "weakly-referenced object no longer exists");  | 
415  | 0  |         return 0;  | 
416  | 0  |     }  | 
417  | 0  |     return 1;  | 
418  | 0  | }  | 
419  |  |  | 
420  |  |  | 
421  |  | /* If a parameter is a proxy, check that it is still "live" and wrap it,  | 
422  |  |  * replacing the original value with the raw object.  Raises ReferenceError  | 
423  |  |  * if the param is a dead proxy.  | 
424  |  |  */  | 
425  |  | #define UNWRAP(o) \  | 
426  | 0  |         if (PyWeakref_CheckProxy(o)) { \ | 
427  | 0  |             if (!proxy_checkref((PyWeakReference *)o)) \  | 
428  | 0  |                 return NULL; \  | 
429  | 0  |             o = PyWeakref_GET_OBJECT(o); \  | 
430  | 0  |         }  | 
431  |  |  | 
432  |  | #define WRAP_UNARY(method, generic) \  | 
433  |  |     static PyObject * \  | 
434  | 0  |     method(PyObject *proxy) { \ | 
435  | 0  |         UNWRAP(proxy); \  | 
436  | 0  |         Py_INCREF(proxy); \  | 
437  | 0  |         PyObject* res = generic(proxy); \  | 
438  | 0  |         Py_DECREF(proxy); \  | 
439  | 0  |         return res; \  | 
440  | 0  |     }  | 
441  |  |  | 
442  |  | #define WRAP_BINARY(method, generic) \  | 
443  |  |     static PyObject * \  | 
444  | 0  |     method(PyObject *x, PyObject *y) { \ | 
445  | 0  |         UNWRAP(x); \  | 
446  | 0  |         UNWRAP(y); \  | 
447  | 0  |         Py_INCREF(x); \  | 
448  | 0  |         Py_INCREF(y); \  | 
449  | 0  |         PyObject* res = generic(x, y); \  | 
450  | 0  |         Py_DECREF(x); \  | 
451  | 0  |         Py_DECREF(y); \  | 
452  | 0  |         return res; \  | 
453  | 0  |     }  | 
454  |  |  | 
455  |  | /* Note that the third arg needs to be checked for NULL since the tp_call  | 
456  |  |  * slot can receive NULL for this arg.  | 
457  |  |  */  | 
458  |  | #define WRAP_TERNARY(method, generic) \  | 
459  |  |     static PyObject * \  | 
460  | 0  |     method(PyObject *proxy, PyObject *v, PyObject *w) { \ | 
461  | 0  |         UNWRAP(proxy); \  | 
462  | 0  |         UNWRAP(v); \  | 
463  | 0  |         if (w != NULL) \  | 
464  | 0  |             UNWRAP(w); \  | 
465  | 0  |         Py_INCREF(proxy); \  | 
466  | 0  |         Py_INCREF(v); \  | 
467  | 0  |         Py_XINCREF(w); \  | 
468  | 0  |         PyObject* res = generic(proxy, v, w); \  | 
469  | 0  |         Py_DECREF(proxy); \  | 
470  | 0  |         Py_DECREF(v); \  | 
471  | 0  |         Py_XDECREF(w); \  | 
472  | 0  |         return res; \  | 
473  | 0  |     }  | 
474  |  |  | 
475  |  | #define WRAP_METHOD(method, special) \  | 
476  |  |     static PyObject * \  | 
477  | 0  |     method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \ | 
478  | 0  |             _Py_IDENTIFIER(special); \  | 
479  | 0  |             UNWRAP(proxy); \  | 
480  | 0  |             Py_INCREF(proxy); \  | 
481  | 0  |             PyObject* res = _PyObject_CallMethodId(proxy, &PyId_##special, NULL); \  | 
482  | 0  |             Py_DECREF(proxy); \  | 
483  | 0  |             return res; \  | 
484  | 0  |         }  | 
485  |  |  | 
486  |  |  | 
487  |  | /* direct slots */  | 
488  |  |  | 
489  | 0  | WRAP_BINARY(proxy_getattr, PyObject_GetAttr)  | 
490  | 0  | WRAP_UNARY(proxy_str, PyObject_Str)  | 
491  | 0  | WRAP_TERNARY(proxy_call, PyObject_Call)  | 
492  |  |  | 
493  |  | static PyObject *  | 
494  |  | proxy_repr(PyWeakReference *proxy)  | 
495  | 0  | { | 
496  | 0  |     return PyUnicode_FromFormat(  | 
497  | 0  |         "<weakproxy at %p to %s at %p>",  | 
498  | 0  |         proxy,  | 
499  | 0  |         Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,  | 
500  | 0  |         PyWeakref_GET_OBJECT(proxy));  | 
501  | 0  | }  | 
502  |  |  | 
503  |  |  | 
504  |  | static int  | 
505  |  | proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)  | 
506  | 0  | { | 
507  | 0  |     if (!proxy_checkref(proxy))  | 
508  | 0  |         return -1;  | 
509  | 0  |     PyObject *obj = PyWeakref_GET_OBJECT(proxy);  | 
510  | 0  |     Py_INCREF(obj);  | 
511  | 0  |     int res = PyObject_SetAttr(obj, name, value);  | 
512  | 0  |     Py_DECREF(obj);  | 
513  | 0  |     return res;  | 
514  | 0  | }  | 
515  |  |  | 
516  |  | static PyObject *  | 
517  |  | proxy_richcompare(PyObject *proxy, PyObject *v, int op)  | 
518  | 0  | { | 
519  | 0  |     UNWRAP(proxy);  | 
520  | 0  |     UNWRAP(v);  | 
521  | 0  |     return PyObject_RichCompare(proxy, v, op);  | 
522  | 0  | }  | 
523  |  |  | 
524  |  | /* number slots */  | 
525  | 0  | WRAP_BINARY(proxy_add, PyNumber_Add)  | 
526  | 0  | WRAP_BINARY(proxy_sub, PyNumber_Subtract)  | 
527  | 0  | WRAP_BINARY(proxy_mul, PyNumber_Multiply)  | 
528  | 0  | WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)  | 
529  | 0  | WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)  | 
530  | 0  | WRAP_BINARY(proxy_mod, PyNumber_Remainder)  | 
531  | 0  | WRAP_BINARY(proxy_divmod, PyNumber_Divmod)  | 
532  | 0  | WRAP_TERNARY(proxy_pow, PyNumber_Power)  | 
533  | 0  | WRAP_UNARY(proxy_neg, PyNumber_Negative)  | 
534  | 0  | WRAP_UNARY(proxy_pos, PyNumber_Positive)  | 
535  | 0  | WRAP_UNARY(proxy_abs, PyNumber_Absolute)  | 
536  | 0  | WRAP_UNARY(proxy_invert, PyNumber_Invert)  | 
537  | 0  | WRAP_BINARY(proxy_lshift, PyNumber_Lshift)  | 
538  | 0  | WRAP_BINARY(proxy_rshift, PyNumber_Rshift)  | 
539  | 0  | WRAP_BINARY(proxy_and, PyNumber_And)  | 
540  | 0  | WRAP_BINARY(proxy_xor, PyNumber_Xor)  | 
541  | 0  | WRAP_BINARY(proxy_or, PyNumber_Or)  | 
542  | 0  | WRAP_UNARY(proxy_int, PyNumber_Long)  | 
543  | 0  | WRAP_UNARY(proxy_float, PyNumber_Float)  | 
544  | 0  | WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)  | 
545  | 0  | WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)  | 
546  | 0  | WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)  | 
547  | 0  | WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)  | 
548  | 0  | WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)  | 
549  | 0  | WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)  | 
550  | 0  | WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)  | 
551  | 0  | WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)  | 
552  | 0  | WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)  | 
553  | 0  | WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)  | 
554  | 0  | WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)  | 
555  | 0  | WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)  | 
556  | 0  | WRAP_UNARY(proxy_index, PyNumber_Index)  | 
557  | 0  | WRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply)  | 
558  | 0  | WRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply)  | 
559  |  |  | 
560  |  | static int  | 
561  |  | proxy_bool(PyWeakReference *proxy)  | 
562  | 0  | { | 
563  | 0  |     PyObject *o = PyWeakref_GET_OBJECT(proxy);  | 
564  | 0  |     if (!proxy_checkref(proxy)) { | 
565  | 0  |         return -1;  | 
566  | 0  |     }  | 
567  | 0  |     Py_INCREF(o);  | 
568  | 0  |     int res = PyObject_IsTrue(o);  | 
569  | 0  |     Py_DECREF(o);  | 
570  | 0  |     return res;  | 
571  | 0  | }  | 
572  |  |  | 
573  |  | static void  | 
574  |  | proxy_dealloc(PyWeakReference *self)  | 
575  | 0  | { | 
576  | 0  |     if (self->wr_callback != NULL)  | 
577  | 0  |         PyObject_GC_UnTrack((PyObject *)self);  | 
578  | 0  |     clear_weakref(self);  | 
579  | 0  |     PyObject_GC_Del(self);  | 
580  | 0  | }  | 
581  |  |  | 
582  |  | /* sequence slots */  | 
583  |  |  | 
584  |  | static int  | 
585  |  | proxy_contains(PyWeakReference *proxy, PyObject *value)  | 
586  | 0  | { | 
587  | 0  |     if (!proxy_checkref(proxy))  | 
588  | 0  |         return -1;  | 
589  |  |  | 
590  | 0  |     PyObject *obj = PyWeakref_GET_OBJECT(proxy);  | 
591  | 0  |     Py_INCREF(obj);  | 
592  | 0  |     int res = PySequence_Contains(obj, value);  | 
593  | 0  |     Py_DECREF(obj);  | 
594  | 0  |     return res;  | 
595  | 0  | }  | 
596  |  |  | 
597  |  | /* mapping slots */  | 
598  |  |  | 
599  |  | static Py_ssize_t  | 
600  |  | proxy_length(PyWeakReference *proxy)  | 
601  | 0  | { | 
602  | 0  |     if (!proxy_checkref(proxy))  | 
603  | 0  |         return -1;  | 
604  |  |  | 
605  | 0  |     PyObject *obj = PyWeakref_GET_OBJECT(proxy);  | 
606  | 0  |     Py_INCREF(obj);  | 
607  | 0  |     Py_ssize_t res = PyObject_Length(obj);  | 
608  | 0  |     Py_DECREF(obj);  | 
609  | 0  |     return res;  | 
610  | 0  | }  | 
611  |  |  | 
612  | 0  | WRAP_BINARY(proxy_getitem, PyObject_GetItem)  | 
613  |  |  | 
614  |  | static int  | 
615  |  | proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)  | 
616  | 0  | { | 
617  | 0  |     if (!proxy_checkref(proxy))  | 
618  | 0  |         return -1;  | 
619  |  |  | 
620  | 0  |     PyObject *obj = PyWeakref_GET_OBJECT(proxy);  | 
621  | 0  |     Py_INCREF(obj);  | 
622  | 0  |     int res;  | 
623  | 0  |     if (value == NULL) { | 
624  | 0  |         res = PyObject_DelItem(obj, key);  | 
625  | 0  |     } else { | 
626  | 0  |         res = PyObject_SetItem(obj, key, value);  | 
627  | 0  |     }  | 
628  | 0  |     Py_DECREF(obj);  | 
629  | 0  |     return res;  | 
630  | 0  | }  | 
631  |  |  | 
632  |  | /* iterator slots */  | 
633  |  |  | 
634  |  | static PyObject *  | 
635  |  | proxy_iter(PyWeakReference *proxy)  | 
636  | 0  | { | 
637  | 0  |     if (!proxy_checkref(proxy))  | 
638  | 0  |         return NULL;  | 
639  | 0  |     PyObject *obj = PyWeakref_GET_OBJECT(proxy);  | 
640  | 0  |     Py_INCREF(obj);  | 
641  | 0  |     PyObject* res = PyObject_GetIter(obj);  | 
642  | 0  |     Py_DECREF(obj);  | 
643  | 0  |     return res;  | 
644  | 0  | }  | 
645  |  |  | 
646  |  | static PyObject *  | 
647  |  | proxy_iternext(PyWeakReference *proxy)  | 
648  | 0  | { | 
649  | 0  |     if (!proxy_checkref(proxy))  | 
650  | 0  |         return NULL;  | 
651  |  |  | 
652  | 0  |     PyObject *obj = PyWeakref_GET_OBJECT(proxy);  | 
653  | 0  |     Py_INCREF(obj);  | 
654  | 0  |     PyObject* res = PyIter_Next(obj);  | 
655  | 0  |     Py_DECREF(obj);  | 
656  | 0  |     return res;  | 
657  | 0  | }  | 
658  |  |  | 
659  |  |  | 
660  | 0  | WRAP_METHOD(proxy_bytes, __bytes__)  | 
661  |  |  | 
662  |  |  | 
663  |  | static PyMethodDef proxy_methods[] = { | 
664  |  |         {"__bytes__", proxy_bytes, METH_NOARGS}, | 
665  |  |         {NULL, NULL} | 
666  |  | };  | 
667  |  |  | 
668  |  |  | 
669  |  | static PyNumberMethods proxy_as_number = { | 
670  |  |     proxy_add,              /*nb_add*/  | 
671  |  |     proxy_sub,              /*nb_subtract*/  | 
672  |  |     proxy_mul,              /*nb_multiply*/  | 
673  |  |     proxy_mod,              /*nb_remainder*/  | 
674  |  |     proxy_divmod,           /*nb_divmod*/  | 
675  |  |     proxy_pow,              /*nb_power*/  | 
676  |  |     proxy_neg,              /*nb_negative*/  | 
677  |  |     proxy_pos,              /*nb_positive*/  | 
678  |  |     proxy_abs,              /*nb_absolute*/  | 
679  |  |     (inquiry)proxy_bool,    /*nb_bool*/  | 
680  |  |     proxy_invert,           /*nb_invert*/  | 
681  |  |     proxy_lshift,           /*nb_lshift*/  | 
682  |  |     proxy_rshift,           /*nb_rshift*/  | 
683  |  |     proxy_and,              /*nb_and*/  | 
684  |  |     proxy_xor,              /*nb_xor*/  | 
685  |  |     proxy_or,               /*nb_or*/  | 
686  |  |     proxy_int,              /*nb_int*/  | 
687  |  |     0,                      /*nb_reserved*/  | 
688  |  |     proxy_float,            /*nb_float*/  | 
689  |  |     proxy_iadd,             /*nb_inplace_add*/  | 
690  |  |     proxy_isub,             /*nb_inplace_subtract*/  | 
691  |  |     proxy_imul,             /*nb_inplace_multiply*/  | 
692  |  |     proxy_imod,             /*nb_inplace_remainder*/  | 
693  |  |     proxy_ipow,             /*nb_inplace_power*/  | 
694  |  |     proxy_ilshift,          /*nb_inplace_lshift*/  | 
695  |  |     proxy_irshift,          /*nb_inplace_rshift*/  | 
696  |  |     proxy_iand,             /*nb_inplace_and*/  | 
697  |  |     proxy_ixor,             /*nb_inplace_xor*/  | 
698  |  |     proxy_ior,              /*nb_inplace_or*/  | 
699  |  |     proxy_floor_div,        /*nb_floor_divide*/  | 
700  |  |     proxy_true_div,         /*nb_true_divide*/  | 
701  |  |     proxy_ifloor_div,       /*nb_inplace_floor_divide*/  | 
702  |  |     proxy_itrue_div,        /*nb_inplace_true_divide*/  | 
703  |  |     proxy_index,            /*nb_index*/  | 
704  |  |     proxy_matmul,           /*nb_matrix_multiply*/  | 
705  |  |     proxy_imatmul,          /*nb_inplace_matrix_multiply*/  | 
706  |  | };  | 
707  |  |  | 
708  |  | static PySequenceMethods proxy_as_sequence = { | 
709  |  |     (lenfunc)proxy_length,      /*sq_length*/  | 
710  |  |     0,                          /*sq_concat*/  | 
711  |  |     0,                          /*sq_repeat*/  | 
712  |  |     0,                          /*sq_item*/  | 
713  |  |     0,                          /*sq_slice*/  | 
714  |  |     0,                          /*sq_ass_item*/  | 
715  |  |     0,                           /*sq_ass_slice*/  | 
716  |  |     (objobjproc)proxy_contains, /* sq_contains */  | 
717  |  | };  | 
718  |  |  | 
719  |  | static PyMappingMethods proxy_as_mapping = { | 
720  |  |     (lenfunc)proxy_length,        /*mp_length*/  | 
721  |  |     proxy_getitem,                /*mp_subscript*/  | 
722  |  |     (objobjargproc)proxy_setitem, /*mp_ass_subscript*/  | 
723  |  | };  | 
724  |  |  | 
725  |  |  | 
726  |  | PyTypeObject  | 
727  |  | _PyWeakref_ProxyType = { | 
728  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0)  | 
729  |  |     "weakproxy",  | 
730  |  |     sizeof(PyWeakReference),  | 
731  |  |     0,  | 
732  |  |     /* methods */  | 
733  |  |     (destructor)proxy_dealloc,          /* tp_dealloc */  | 
734  |  |     0,                                  /* tp_vectorcall_offset */  | 
735  |  |     0,                                  /* tp_getattr */  | 
736  |  |     0,                                  /* tp_setattr */  | 
737  |  |     0,                                  /* tp_as_async */  | 
738  |  |     (reprfunc)proxy_repr,               /* tp_repr */  | 
739  |  |     &proxy_as_number,                   /* tp_as_number */  | 
740  |  |     &proxy_as_sequence,                 /* tp_as_sequence */  | 
741  |  |     &proxy_as_mapping,                  /* tp_as_mapping */  | 
742  |  |     0,                                  /* tp_hash */  | 
743  |  |     0,                                  /* tp_call */  | 
744  |  |     proxy_str,                          /* tp_str */  | 
745  |  |     proxy_getattr,                      /* tp_getattro */  | 
746  |  |     (setattrofunc)proxy_setattr,        /* tp_setattro */  | 
747  |  |     0,                                  /* tp_as_buffer */  | 
748  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */  | 
749  |  |     0,                                  /* tp_doc */  | 
750  |  |     (traverseproc)gc_traverse,          /* tp_traverse */  | 
751  |  |     (inquiry)gc_clear,                  /* tp_clear */  | 
752  |  |     proxy_richcompare,                  /* tp_richcompare */  | 
753  |  |     0,                                  /* tp_weaklistoffset */  | 
754  |  |     (getiterfunc)proxy_iter,            /* tp_iter */  | 
755  |  |     (iternextfunc)proxy_iternext,       /* tp_iternext */  | 
756  |  |         proxy_methods,                      /* tp_methods */  | 
757  |  | };  | 
758  |  |  | 
759  |  |  | 
760  |  | PyTypeObject  | 
761  |  | _PyWeakref_CallableProxyType = { | 
762  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0)  | 
763  |  |     "weakcallableproxy",  | 
764  |  |     sizeof(PyWeakReference),  | 
765  |  |     0,  | 
766  |  |     /* methods */  | 
767  |  |     (destructor)proxy_dealloc,          /* tp_dealloc */  | 
768  |  |     0,                                  /* tp_vectorcall_offset */  | 
769  |  |     0,                                  /* tp_getattr */  | 
770  |  |     0,                                  /* tp_setattr */  | 
771  |  |     0,                                  /* tp_as_async */  | 
772  |  |     (unaryfunc)proxy_repr,              /* tp_repr */  | 
773  |  |     &proxy_as_number,                   /* tp_as_number */  | 
774  |  |     &proxy_as_sequence,                 /* tp_as_sequence */  | 
775  |  |     &proxy_as_mapping,                  /* tp_as_mapping */  | 
776  |  |     0,                                  /* tp_hash */  | 
777  |  |     proxy_call,                         /* tp_call */  | 
778  |  |     proxy_str,                          /* tp_str */  | 
779  |  |     proxy_getattr,                      /* tp_getattro */  | 
780  |  |     (setattrofunc)proxy_setattr,        /* tp_setattro */  | 
781  |  |     0,                                  /* tp_as_buffer */  | 
782  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */  | 
783  |  |     0,                                  /* tp_doc */  | 
784  |  |     (traverseproc)gc_traverse,          /* tp_traverse */  | 
785  |  |     (inquiry)gc_clear,                  /* tp_clear */  | 
786  |  |     proxy_richcompare,                  /* tp_richcompare */  | 
787  |  |     0,                                  /* tp_weaklistoffset */  | 
788  |  |     (getiterfunc)proxy_iter,            /* tp_iter */  | 
789  |  |     (iternextfunc)proxy_iternext,       /* tp_iternext */  | 
790  |  | };  | 
791  |  |  | 
792  |  |  | 
793  |  |  | 
794  |  | PyObject *  | 
795  |  | PyWeakref_NewRef(PyObject *ob, PyObject *callback)  | 
796  | 6.60k  | { | 
797  | 6.60k  |     PyWeakReference *result = NULL;  | 
798  | 6.60k  |     PyWeakReference **list;  | 
799  | 6.60k  |     PyWeakReference *ref, *proxy;  | 
800  |  |  | 
801  | 6.60k  |     if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { | 
802  | 0  |         PyErr_Format(PyExc_TypeError,  | 
803  | 0  |                      "cannot create weak reference to '%s' object",  | 
804  | 0  |                      Py_TYPE(ob)->tp_name);  | 
805  | 0  |         return NULL;  | 
806  | 0  |     }  | 
807  | 6.60k  |     list = GET_WEAKREFS_LISTPTR(ob);  | 
808  | 6.60k  |     get_basic_refs(*list, &ref, &proxy);  | 
809  | 6.60k  |     if (callback == Py_None)  | 
810  | 0  |         callback = NULL;  | 
811  | 6.60k  |     if (callback == NULL)  | 
812  |  |         /* return existing weak reference if it exists */  | 
813  | 5.72k  |         result = ref;  | 
814  | 6.60k  |     if (result != NULL)  | 
815  | 789  |         Py_INCREF(result);  | 
816  | 5.81k  |     else { | 
817  |  |         /* Note: new_weakref() can trigger cyclic GC, so the weakref  | 
818  |  |            list on ob can be mutated.  This means that the ref and  | 
819  |  |            proxy pointers we got back earlier may have been collected,  | 
820  |  |            so we need to compute these values again before we use  | 
821  |  |            them. */  | 
822  | 5.81k  |         result = new_weakref(ob, callback);  | 
823  | 5.81k  |         if (result != NULL) { | 
824  | 5.81k  |             get_basic_refs(*list, &ref, &proxy);  | 
825  | 5.81k  |             if (callback == NULL) { | 
826  | 4.93k  |                 if (ref == NULL)  | 
827  | 4.93k  |                     insert_head(result, list);  | 
828  | 0  |                 else { | 
829  |  |                     /* Someone else added a ref without a callback  | 
830  |  |                        during GC.  Return that one instead of this one  | 
831  |  |                        to avoid violating the invariants of the list  | 
832  |  |                        of weakrefs for ob. */  | 
833  | 0  |                     Py_DECREF(result);  | 
834  | 0  |                     Py_INCREF(ref);  | 
835  | 0  |                     result = ref;  | 
836  | 0  |                 }  | 
837  | 4.93k  |             }  | 
838  | 877  |             else { | 
839  | 877  |                 PyWeakReference *prev;  | 
840  |  |  | 
841  | 877  |                 prev = (proxy == NULL) ? ref : proxy;  | 
842  | 877  |                 if (prev == NULL)  | 
843  | 0  |                     insert_head(result, list);  | 
844  | 877  |                 else  | 
845  | 877  |                     insert_after(result, prev);  | 
846  | 877  |             }  | 
847  | 5.81k  |         }  | 
848  | 5.81k  |     }  | 
849  | 6.60k  |     return (PyObject *) result;  | 
850  | 6.60k  | }  | 
851  |  |  | 
852  |  |  | 
853  |  | PyObject *  | 
854  |  | PyWeakref_NewProxy(PyObject *ob, PyObject *callback)  | 
855  | 0  | { | 
856  | 0  |     PyWeakReference *result = NULL;  | 
857  | 0  |     PyWeakReference **list;  | 
858  | 0  |     PyWeakReference *ref, *proxy;  | 
859  |  | 
  | 
860  | 0  |     if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { | 
861  | 0  |         PyErr_Format(PyExc_TypeError,  | 
862  | 0  |                      "cannot create weak reference to '%s' object",  | 
863  | 0  |                      Py_TYPE(ob)->tp_name);  | 
864  | 0  |         return NULL;  | 
865  | 0  |     }  | 
866  | 0  |     list = GET_WEAKREFS_LISTPTR(ob);  | 
867  | 0  |     get_basic_refs(*list, &ref, &proxy);  | 
868  | 0  |     if (callback == Py_None)  | 
869  | 0  |         callback = NULL;  | 
870  | 0  |     if (callback == NULL)  | 
871  |  |         /* attempt to return an existing weak reference if it exists */  | 
872  | 0  |         result = proxy;  | 
873  | 0  |     if (result != NULL)  | 
874  | 0  |         Py_INCREF(result);  | 
875  | 0  |     else { | 
876  |  |         /* Note: new_weakref() can trigger cyclic GC, so the weakref  | 
877  |  |            list on ob can be mutated.  This means that the ref and  | 
878  |  |            proxy pointers we got back earlier may have been collected,  | 
879  |  |            so we need to compute these values again before we use  | 
880  |  |            them. */  | 
881  | 0  |         result = new_weakref(ob, callback);  | 
882  | 0  |         if (result != NULL) { | 
883  | 0  |             PyWeakReference *prev;  | 
884  |  | 
  | 
885  | 0  |             if (PyCallable_Check(ob))  | 
886  | 0  |                 Py_TYPE(result) = &_PyWeakref_CallableProxyType;  | 
887  | 0  |             else  | 
888  | 0  |                 Py_TYPE(result) = &_PyWeakref_ProxyType;  | 
889  | 0  |             get_basic_refs(*list, &ref, &proxy);  | 
890  | 0  |             if (callback == NULL) { | 
891  | 0  |                 if (proxy != NULL) { | 
892  |  |                     /* Someone else added a proxy without a callback  | 
893  |  |                        during GC.  Return that one instead of this one  | 
894  |  |                        to avoid violating the invariants of the list  | 
895  |  |                        of weakrefs for ob. */  | 
896  | 0  |                     Py_DECREF(result);  | 
897  | 0  |                     result = proxy;  | 
898  | 0  |                     Py_INCREF(result);  | 
899  | 0  |                     goto skip_insert;  | 
900  | 0  |                 }  | 
901  | 0  |                 prev = ref;  | 
902  | 0  |             }  | 
903  | 0  |             else  | 
904  | 0  |                 prev = (proxy == NULL) ? ref : proxy;  | 
905  |  |  | 
906  | 0  |             if (prev == NULL)  | 
907  | 0  |                 insert_head(result, list);  | 
908  | 0  |             else  | 
909  | 0  |                 insert_after(result, prev);  | 
910  | 0  |         skip_insert:  | 
911  | 0  |             ;  | 
912  | 0  |         }  | 
913  | 0  |     }  | 
914  | 0  |     return (PyObject *) result;  | 
915  | 0  | }  | 
916  |  |  | 
917  |  |  | 
918  |  | PyObject *  | 
919  |  | PyWeakref_GetObject(PyObject *ref)  | 
920  | 270  | { | 
921  | 270  |     if (ref == NULL || !PyWeakref_Check(ref)) { | 
922  | 0  |         PyErr_BadInternalCall();  | 
923  | 0  |         return NULL;  | 
924  | 0  |     }  | 
925  | 270  |     return PyWeakref_GET_OBJECT(ref);  | 
926  | 270  | }  | 
927  |  |  | 
928  |  | /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's  | 
929  |  |  * handle_weakrefs().  | 
930  |  |  */  | 
931  |  | static void  | 
932  |  | handle_callback(PyWeakReference *ref, PyObject *callback)  | 
933  | 362  | { | 
934  | 362  |     PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);  | 
935  |  |  | 
936  | 362  |     if (cbresult == NULL)  | 
937  | 0  |         PyErr_WriteUnraisable(callback);  | 
938  | 362  |     else  | 
939  | 362  |         Py_DECREF(cbresult);  | 
940  | 362  | }  | 
941  |  |  | 
942  |  | /* This function is called by the tp_dealloc handler to clear weak references.  | 
943  |  |  *  | 
944  |  |  * This iterates through the weak references for 'object' and calls callbacks  | 
945  |  |  * for those references which have one.  It returns when all callbacks have  | 
946  |  |  * been attempted.  | 
947  |  |  */  | 
948  |  | void  | 
949  |  | PyObject_ClearWeakRefs(PyObject *object)  | 
950  | 2.00k  | { | 
951  | 2.00k  |     PyWeakReference **list;  | 
952  |  |  | 
953  | 2.00k  |     if (object == NULL  | 
954  | 2.00k  |         || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))  | 
955  | 2.00k  |         || object->ob_refcnt != 0) { | 
956  | 0  |         PyErr_BadInternalCall();  | 
957  | 0  |         return;  | 
958  | 0  |     }  | 
959  | 2.00k  |     list = GET_WEAKREFS_LISTPTR(object);  | 
960  |  |     /* Remove the callback-less basic and proxy references */  | 
961  | 2.00k  |     if (*list != NULL && (*list)->wr_callback == NULL) { | 
962  | 0  |         clear_weakref(*list);  | 
963  | 0  |         if (*list != NULL && (*list)->wr_callback == NULL)  | 
964  | 0  |             clear_weakref(*list);  | 
965  | 0  |     }  | 
966  | 2.00k  |     if (*list != NULL) { | 
967  | 362  |         PyWeakReference *current = *list;  | 
968  | 362  |         Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);  | 
969  | 362  |         PyObject *err_type, *err_value, *err_tb;  | 
970  |  |  | 
971  | 362  |         PyErr_Fetch(&err_type, &err_value, &err_tb);  | 
972  | 362  |         if (count == 1) { | 
973  | 362  |             PyObject *callback = current->wr_callback;  | 
974  |  |  | 
975  | 362  |             current->wr_callback = NULL;  | 
976  | 362  |             clear_weakref(current);  | 
977  | 362  |             if (callback != NULL) { | 
978  | 362  |                 if (((PyObject *)current)->ob_refcnt > 0)  | 
979  | 362  |                     handle_callback(current, callback);  | 
980  | 362  |                 Py_DECREF(callback);  | 
981  | 362  |             }  | 
982  | 362  |         }  | 
983  | 0  |         else { | 
984  | 0  |             PyObject *tuple;  | 
985  | 0  |             Py_ssize_t i = 0;  | 
986  |  | 
  | 
987  | 0  |             tuple = PyTuple_New(count * 2);  | 
988  | 0  |             if (tuple == NULL) { | 
989  | 0  |                 _PyErr_ChainExceptions(err_type, err_value, err_tb);  | 
990  | 0  |                 return;  | 
991  | 0  |             }  | 
992  |  |  | 
993  | 0  |             for (i = 0; i < count; ++i) { | 
994  | 0  |                 PyWeakReference *next = current->wr_next;  | 
995  |  | 
  | 
996  | 0  |                 if (((PyObject *)current)->ob_refcnt > 0)  | 
997  | 0  |                 { | 
998  | 0  |                     Py_INCREF(current);  | 
999  | 0  |                     PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);  | 
1000  | 0  |                     PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);  | 
1001  | 0  |                 }  | 
1002  | 0  |                 else { | 
1003  | 0  |                     Py_DECREF(current->wr_callback);  | 
1004  | 0  |                 }  | 
1005  | 0  |                 current->wr_callback = NULL;  | 
1006  | 0  |                 clear_weakref(current);  | 
1007  | 0  |                 current = next;  | 
1008  | 0  |             }  | 
1009  | 0  |             for (i = 0; i < count; ++i) { | 
1010  | 0  |                 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);  | 
1011  |  |  | 
1012  |  |                 /* The tuple may have slots left to NULL */  | 
1013  | 0  |                 if (callback != NULL) { | 
1014  | 0  |                     PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);  | 
1015  | 0  |                     handle_callback((PyWeakReference *)item, callback);  | 
1016  | 0  |                 }  | 
1017  | 0  |             }  | 
1018  | 0  |             Py_DECREF(tuple);  | 
1019  | 0  |         }  | 
1020  | 362  |         assert(!PyErr_Occurred());  | 
1021  | 362  |         PyErr_Restore(err_type, err_value, err_tb);  | 
1022  | 362  |     }  | 
1023  | 2.00k  | }  |