/src/Python-3.8.3/Modules/_weakref.c
Line  | Count  | Source  | 
1  |  | #include "Python.h"  | 
2  |  |  | 
3  |  |  | 
4  |  | #define GET_WEAKREFS_LISTPTR(o) \  | 
5  | 0  |         ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))  | 
6  |  |  | 
7  |  | /*[clinic input]  | 
8  |  | module _weakref  | 
9  |  | [clinic start generated code]*/  | 
10  |  | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ffec73b85846596d]*/  | 
11  |  |  | 
12  |  | #include "clinic/_weakref.c.h"  | 
13  |  |  | 
14  |  | /*[clinic input]  | 
15  |  |  | 
16  |  | _weakref.getweakrefcount -> Py_ssize_t  | 
17  |  |  | 
18  |  |   object: object  | 
19  |  |   /  | 
20  |  |  | 
21  |  | Return the number of weak references to 'object'.  | 
22  |  | [clinic start generated code]*/  | 
23  |  |  | 
24  |  | static Py_ssize_t  | 
25  |  | _weakref_getweakrefcount_impl(PyObject *module, PyObject *object)  | 
26  |  | /*[clinic end generated code: output=301806d59558ff3e input=cedb69711b6a2507]*/  | 
27  | 0  | { | 
28  | 0  |     PyWeakReference **list;  | 
29  |  | 
  | 
30  | 0  |     if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(object)))  | 
31  | 0  |         return 0;  | 
32  |  |  | 
33  | 0  |     list = GET_WEAKREFS_LISTPTR(object);  | 
34  | 0  |     return _PyWeakref_GetWeakrefCount(*list);  | 
35  | 0  | }  | 
36  |  |  | 
37  |  |  | 
38  |  | static int  | 
39  |  | is_dead_weakref(PyObject *value)  | 
40  | 0  | { | 
41  | 0  |     if (!PyWeakref_Check(value)) { | 
42  | 0  |         PyErr_SetString(PyExc_TypeError, "not a weakref");  | 
43  | 0  |         return -1;  | 
44  | 0  |     }  | 
45  | 0  |     return PyWeakref_GET_OBJECT(value) == Py_None;  | 
46  | 0  | }  | 
47  |  |  | 
48  |  | /*[clinic input]  | 
49  |  |  | 
50  |  | _weakref._remove_dead_weakref -> object  | 
51  |  |  | 
52  |  |   dct: object(subclass_of='&PyDict_Type')  | 
53  |  |   key: object  | 
54  |  |   /  | 
55  |  |  | 
56  |  | Atomically remove key from dict if it points to a dead weakref.  | 
57  |  | [clinic start generated code]*/  | 
58  |  |  | 
59  |  | static PyObject *  | 
60  |  | _weakref__remove_dead_weakref_impl(PyObject *module, PyObject *dct,  | 
61  |  |                                    PyObject *key)  | 
62  |  | /*[clinic end generated code: output=d9ff53061fcb875c input=19fc91f257f96a1d]*/  | 
63  | 0  | { | 
64  | 0  |     if (_PyDict_DelItemIf(dct, key, is_dead_weakref) < 0) { | 
65  | 0  |         if (PyErr_ExceptionMatches(PyExc_KeyError))  | 
66  |  |             /* This function is meant to allow safe weak-value dicts  | 
67  |  |                with GC in another thread (see issue #28427), so it's  | 
68  |  |                ok if the key doesn't exist anymore.  | 
69  |  |                */  | 
70  | 0  |             PyErr_Clear();  | 
71  | 0  |         else  | 
72  | 0  |             return NULL;  | 
73  | 0  |     }  | 
74  | 0  |     Py_RETURN_NONE;  | 
75  | 0  | }  | 
76  |  |  | 
77  |  |  | 
78  |  | PyDoc_STRVAR(weakref_getweakrefs__doc__,  | 
79  |  | "getweakrefs(object) -- return a list of all weak reference objects\n"  | 
80  |  | "that point to 'object'.");  | 
81  |  |  | 
82  |  | static PyObject *  | 
83  |  | weakref_getweakrefs(PyObject *self, PyObject *object)  | 
84  | 0  | { | 
85  | 0  |     PyObject *result = NULL;  | 
86  |  | 
  | 
87  | 0  |     if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { | 
88  | 0  |         PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);  | 
89  | 0  |         Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list);  | 
90  |  | 
  | 
91  | 0  |         result = PyList_New(count);  | 
92  | 0  |         if (result != NULL) { | 
93  | 0  |             PyWeakReference *current = *list;  | 
94  | 0  |             Py_ssize_t i;  | 
95  | 0  |             for (i = 0; i < count; ++i) { | 
96  | 0  |                 PyList_SET_ITEM(result, i, (PyObject *) current);  | 
97  | 0  |                 Py_INCREF(current);  | 
98  | 0  |                 current = current->wr_next;  | 
99  | 0  |             }  | 
100  | 0  |         }  | 
101  | 0  |     }  | 
102  | 0  |     else { | 
103  | 0  |         result = PyList_New(0);  | 
104  | 0  |     }  | 
105  | 0  |     return result;  | 
106  | 0  | }  | 
107  |  |  | 
108  |  |  | 
109  |  | PyDoc_STRVAR(weakref_proxy__doc__,  | 
110  |  | "proxy(object[, callback]) -- create a proxy object that weakly\n"  | 
111  |  | "references 'object'.  'callback', if given, is called with a\n"  | 
112  |  | "reference to the proxy when 'object' is about to be finalized.");  | 
113  |  |  | 
114  |  | static PyObject *  | 
115  |  | weakref_proxy(PyObject *self, PyObject *args)  | 
116  | 0  | { | 
117  | 0  |     PyObject *object;  | 
118  | 0  |     PyObject *callback = NULL;  | 
119  | 0  |     PyObject *result = NULL;  | 
120  |  | 
  | 
121  | 0  |     if (PyArg_UnpackTuple(args, "proxy", 1, 2, &object, &callback)) { | 
122  | 0  |         result = PyWeakref_NewProxy(object, callback);  | 
123  | 0  |     }  | 
124  | 0  |     return result;  | 
125  | 0  | }  | 
126  |  |  | 
127  |  |  | 
128  |  | static PyMethodDef  | 
129  |  | weakref_functions[] =  { | 
130  |  |     _WEAKREF_GETWEAKREFCOUNT_METHODDEF  | 
131  |  |     _WEAKREF__REMOVE_DEAD_WEAKREF_METHODDEF  | 
132  |  |     {"getweakrefs",     weakref_getweakrefs,            METH_O, | 
133  |  |      weakref_getweakrefs__doc__},  | 
134  |  |     {"proxy",           weakref_proxy,                  METH_VARARGS, | 
135  |  |      weakref_proxy__doc__},  | 
136  |  |     {NULL, NULL, 0, NULL} | 
137  |  | };  | 
138  |  |  | 
139  |  |  | 
140  |  | static struct PyModuleDef weakrefmodule = { | 
141  |  |     PyModuleDef_HEAD_INIT,  | 
142  |  |     "_weakref",  | 
143  |  |     "Weak-reference support module.",  | 
144  |  |     -1,  | 
145  |  |     weakref_functions,  | 
146  |  |     NULL,  | 
147  |  |     NULL,  | 
148  |  |     NULL,  | 
149  |  |     NULL  | 
150  |  | };  | 
151  |  |  | 
152  |  | PyMODINIT_FUNC  | 
153  |  | PyInit__weakref(void)  | 
154  | 14  | { | 
155  | 14  |     PyObject *m;  | 
156  |  |  | 
157  | 14  |     m = PyModule_Create(&weakrefmodule);  | 
158  |  |  | 
159  | 14  |     if (m != NULL) { | 
160  | 14  |         Py_INCREF(&_PyWeakref_RefType);  | 
161  | 14  |         PyModule_AddObject(m, "ref",  | 
162  | 14  |                            (PyObject *) &_PyWeakref_RefType);  | 
163  | 14  |         Py_INCREF(&_PyWeakref_RefType);  | 
164  | 14  |         PyModule_AddObject(m, "ReferenceType",  | 
165  | 14  |                            (PyObject *) &_PyWeakref_RefType);  | 
166  | 14  |         Py_INCREF(&_PyWeakref_ProxyType);  | 
167  | 14  |         PyModule_AddObject(m, "ProxyType",  | 
168  | 14  |                            (PyObject *) &_PyWeakref_ProxyType);  | 
169  | 14  |         Py_INCREF(&_PyWeakref_CallableProxyType);  | 
170  | 14  |         PyModule_AddObject(m, "CallableProxyType",  | 
171  | 14  |                            (PyObject *) &_PyWeakref_CallableProxyType);  | 
172  | 14  |     }  | 
173  | 14  |     return m;  | 
174  | 14  | }  |