/src/cpython/Modules/_weakref.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "Python.h" |
2 | | #include "pycore_dict.h" // _PyDict_DelItemIf() |
3 | | #include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR() |
4 | | #include "pycore_weakref.h" // _PyWeakref_IS_DEAD() |
5 | | |
6 | | #define GET_WEAKREFS_LISTPTR(o) \ |
7 | 0 | ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o)) |
8 | | |
9 | | /*[clinic input] |
10 | | module _weakref |
11 | | [clinic start generated code]*/ |
12 | | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ffec73b85846596d]*/ |
13 | | |
14 | | #include "clinic/_weakref.c.h" |
15 | | |
16 | | /*[clinic input] |
17 | | _weakref.getweakrefcount -> Py_ssize_t |
18 | | |
19 | | object: object |
20 | | / |
21 | | |
22 | | Return the number of weak references to 'object'. |
23 | | [clinic start generated code]*/ |
24 | | |
25 | | static Py_ssize_t |
26 | | _weakref_getweakrefcount_impl(PyObject *module, PyObject *object) |
27 | | /*[clinic end generated code: output=301806d59558ff3e input=7d4d04fcaccf64d5]*/ |
28 | 0 | { |
29 | 0 | return _PyWeakref_GetWeakrefCount(object); |
30 | 0 | } |
31 | | |
32 | | |
33 | | static int |
34 | | is_dead_weakref(PyObject *value, void *unused) |
35 | 2.91k | { |
36 | 2.91k | if (!PyWeakref_Check(value)) { |
37 | 0 | PyErr_SetString(PyExc_TypeError, "not a weakref"); |
38 | 0 | return -1; |
39 | 0 | } |
40 | 2.91k | return _PyWeakref_IS_DEAD(value); |
41 | 2.91k | } |
42 | | |
43 | | /*[clinic input] |
44 | | |
45 | | _weakref._remove_dead_weakref -> object |
46 | | |
47 | | dct: object(subclass_of='&PyDict_Type') |
48 | | key: object |
49 | | / |
50 | | |
51 | | Atomically remove key from dict if it points to a dead weakref. |
52 | | [clinic start generated code]*/ |
53 | | |
54 | | static PyObject * |
55 | | _weakref__remove_dead_weakref_impl(PyObject *module, PyObject *dct, |
56 | | PyObject *key) |
57 | | /*[clinic end generated code: output=d9ff53061fcb875c input=19fc91f257f96a1d]*/ |
58 | 2.91k | { |
59 | 2.91k | if (_PyDict_DelItemIf(dct, key, is_dead_weakref, NULL) < 0) { |
60 | 0 | return NULL; |
61 | 0 | } |
62 | 2.91k | Py_RETURN_NONE; |
63 | 2.91k | } |
64 | | |
65 | | |
66 | | /*[clinic input] |
67 | | _weakref.getweakrefs |
68 | | object: object |
69 | | / |
70 | | |
71 | | Return a list of all weak reference objects pointing to 'object'. |
72 | | [clinic start generated code]*/ |
73 | | |
74 | | static PyObject * |
75 | | _weakref_getweakrefs(PyObject *module, PyObject *object) |
76 | | /*[clinic end generated code: output=25c7731d8e011824 input=00c6d0e5d3206693]*/ |
77 | 0 | { |
78 | 0 | if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { |
79 | 0 | return PyList_New(0); |
80 | 0 | } |
81 | | |
82 | 0 | PyObject *result = PyList_New(0); |
83 | 0 | if (result == NULL) { |
84 | 0 | return NULL; |
85 | 0 | } |
86 | | |
87 | 0 | LOCK_WEAKREFS(object); |
88 | 0 | PyWeakReference *current = *GET_WEAKREFS_LISTPTR(object); |
89 | 0 | while (current != NULL) { |
90 | 0 | PyObject *curobj = (PyObject *) current; |
91 | 0 | if (_Py_TryIncref(curobj)) { |
92 | 0 | if (PyList_Append(result, curobj)) { |
93 | 0 | UNLOCK_WEAKREFS(object); |
94 | 0 | Py_DECREF(curobj); |
95 | 0 | Py_DECREF(result); |
96 | 0 | return NULL; |
97 | 0 | } |
98 | 0 | else { |
99 | | // Undo our _Py_TryIncref. This is safe to do with the lock |
100 | | // held in free-threaded builds; the list holds a reference to |
101 | | // curobj so we're guaranteed not to invoke the destructor. |
102 | 0 | Py_DECREF(curobj); |
103 | 0 | } |
104 | 0 | } |
105 | 0 | current = current->wr_next; |
106 | 0 | } |
107 | 0 | UNLOCK_WEAKREFS(object); |
108 | 0 | return result; |
109 | 0 | } |
110 | | |
111 | | |
112 | | /*[clinic input] |
113 | | |
114 | | _weakref.proxy |
115 | | object: object |
116 | | callback: object(c_default="NULL") = None |
117 | | / |
118 | | |
119 | | Create a proxy object that weakly references 'object'. |
120 | | |
121 | | 'callback', if given, is called with a reference to the |
122 | | proxy when 'object' is about to be finalized. |
123 | | [clinic start generated code]*/ |
124 | | |
125 | | static PyObject * |
126 | | _weakref_proxy_impl(PyObject *module, PyObject *object, PyObject *callback) |
127 | | /*[clinic end generated code: output=d68fa4ad9ea40519 input=4808adf22fd137e7]*/ |
128 | 0 | { |
129 | 0 | return PyWeakref_NewProxy(object, callback); |
130 | 0 | } |
131 | | |
132 | | |
133 | | static PyMethodDef |
134 | | weakref_functions[] = { |
135 | | _WEAKREF_GETWEAKREFCOUNT_METHODDEF |
136 | | _WEAKREF__REMOVE_DEAD_WEAKREF_METHODDEF |
137 | | _WEAKREF_GETWEAKREFS_METHODDEF |
138 | | _WEAKREF_PROXY_METHODDEF |
139 | | {NULL, NULL, 0, NULL} |
140 | | }; |
141 | | |
142 | | static int |
143 | | weakref_exec(PyObject *module) |
144 | 16 | { |
145 | 16 | if (PyModule_AddObjectRef(module, "ref", (PyObject *) &_PyWeakref_RefType) < 0) { |
146 | 0 | return -1; |
147 | 0 | } |
148 | 16 | if (PyModule_AddObjectRef(module, "ReferenceType", |
149 | 16 | (PyObject *) &_PyWeakref_RefType) < 0) { |
150 | 0 | return -1; |
151 | 0 | } |
152 | 16 | if (PyModule_AddObjectRef(module, "ProxyType", |
153 | 16 | (PyObject *) &_PyWeakref_ProxyType) < 0) { |
154 | 0 | return -1; |
155 | 0 | } |
156 | 16 | if (PyModule_AddObjectRef(module, "CallableProxyType", |
157 | 16 | (PyObject *) &_PyWeakref_CallableProxyType) < 0) { |
158 | 0 | return -1; |
159 | 0 | } |
160 | | |
161 | 16 | return 0; |
162 | 16 | } |
163 | | |
164 | | static struct PyModuleDef_Slot weakref_slots[] = { |
165 | | {Py_mod_exec, weakref_exec}, |
166 | | {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, |
167 | | {Py_mod_gil, Py_MOD_GIL_NOT_USED}, |
168 | | {0, NULL} |
169 | | }; |
170 | | |
171 | | static struct PyModuleDef weakrefmodule = { |
172 | | PyModuleDef_HEAD_INIT, |
173 | | "_weakref", |
174 | | "Weak-reference support module.", |
175 | | 0, |
176 | | weakref_functions, |
177 | | weakref_slots, |
178 | | NULL, |
179 | | NULL, |
180 | | NULL |
181 | | }; |
182 | | |
183 | | PyMODINIT_FUNC |
184 | | PyInit__weakref(void) |
185 | 16 | { |
186 | 16 | return PyModuleDef_Init(&weakrefmodule); |
187 | 16 | } |