Branch data Line data Source code
1 : : #include "Python.h"
2 : : #include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR
3 : :
4 : :
5 : : #define GET_WEAKREFS_LISTPTR(o) \
6 : : ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o))
7 : :
8 : : /*[clinic input]
9 : : module _weakref
10 : : [clinic start generated code]*/
11 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ffec73b85846596d]*/
12 : :
13 : : #include "clinic/_weakref.c.h"
14 : :
15 : : /*[clinic input]
16 : :
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 : 28 : _weakref_getweakrefcount_impl(PyObject *module, PyObject *object)
27 : : /*[clinic end generated code: output=301806d59558ff3e input=cedb69711b6a2507]*/
28 : : {
29 : : PyWeakReference **list;
30 : :
31 [ + + ]: 28 : if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object)))
32 : 1 : return 0;
33 : :
34 : 27 : list = GET_WEAKREFS_LISTPTR(object);
35 : 27 : return _PyWeakref_GetWeakrefCount(*list);
36 : : }
37 : :
38 : :
39 : : static int
40 : 172664 : is_dead_weakref(PyObject *value)
41 : : {
42 [ - + - - : 172664 : if (!PyWeakref_Check(value)) {
- - ]
43 : 0 : PyErr_SetString(PyExc_TypeError, "not a weakref");
44 : 0 : return -1;
45 : : }
46 : 172664 : return PyWeakref_GET_OBJECT(value) == Py_None;
47 : : }
48 : :
49 : : /*[clinic input]
50 : :
51 : : _weakref._remove_dead_weakref -> object
52 : :
53 : : dct: object(subclass_of='&PyDict_Type')
54 : : key: object
55 : : /
56 : :
57 : : Atomically remove key from dict if it points to a dead weakref.
58 : : [clinic start generated code]*/
59 : :
60 : : static PyObject *
61 : 172687 : _weakref__remove_dead_weakref_impl(PyObject *module, PyObject *dct,
62 : : PyObject *key)
63 : : /*[clinic end generated code: output=d9ff53061fcb875c input=19fc91f257f96a1d]*/
64 : : {
65 [ + + ]: 172687 : if (_PyDict_DelItemIf(dct, key, is_dead_weakref) < 0) {
66 [ + - ]: 23 : if (PyErr_ExceptionMatches(PyExc_KeyError))
67 : : /* This function is meant to allow safe weak-value dicts
68 : : with GC in another thread (see issue #28427), so it's
69 : : ok if the key doesn't exist anymore.
70 : : */
71 : 23 : PyErr_Clear();
72 : : else
73 : 0 : return NULL;
74 : : }
75 : 172687 : Py_RETURN_NONE;
76 : : }
77 : :
78 : :
79 : : /*[clinic input]
80 : : _weakref.getweakrefs
81 : : object: object
82 : : /
83 : :
84 : : Return a list of all weak reference objects pointing to 'object'.
85 : : [clinic start generated code]*/
86 : :
87 : : static PyObject *
88 : 7 : _weakref_getweakrefs(PyObject *module, PyObject *object)
89 : : /*[clinic end generated code: output=25c7731d8e011824 input=00c6d0e5d3206693]*/
90 : : {
91 : 7 : PyObject *result = NULL;
92 : :
93 [ + + ]: 7 : if (_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) {
94 : 6 : PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
95 : 6 : Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list);
96 : :
97 : 6 : result = PyList_New(count);
98 [ + - ]: 6 : if (result != NULL) {
99 : 6 : PyWeakReference *current = *list;
100 : : Py_ssize_t i;
101 [ + + ]: 15 : for (i = 0; i < count; ++i) {
102 : 9 : PyList_SET_ITEM(result, i, (PyObject *) current);
103 : 9 : Py_INCREF(current);
104 : 9 : current = current->wr_next;
105 : : }
106 : : }
107 : : }
108 : : else {
109 : 1 : result = PyList_New(0);
110 : : }
111 : 7 : return result;
112 : : }
113 : :
114 : :
115 : : /*[clinic input]
116 : :
117 : : _weakref.proxy
118 : : object: object
119 : : callback: object(c_default="NULL") = None
120 : : /
121 : :
122 : : Create a proxy object that weakly references 'object'.
123 : :
124 : : 'callback', if given, is called with a reference to the
125 : : proxy when 'object' is about to be finalized.
126 : : [clinic start generated code]*/
127 : :
128 : : static PyObject *
129 : 6864 : _weakref_proxy_impl(PyObject *module, PyObject *object, PyObject *callback)
130 : : /*[clinic end generated code: output=d68fa4ad9ea40519 input=4808adf22fd137e7]*/
131 : : {
132 : 6864 : return PyWeakref_NewProxy(object, callback);
133 : : }
134 : :
135 : :
136 : : static PyMethodDef
137 : : weakref_functions[] = {
138 : : _WEAKREF_GETWEAKREFCOUNT_METHODDEF
139 : : _WEAKREF__REMOVE_DEAD_WEAKREF_METHODDEF
140 : : _WEAKREF_GETWEAKREFS_METHODDEF
141 : : _WEAKREF_PROXY_METHODDEF
142 : : {NULL, NULL, 0, NULL}
143 : : };
144 : :
145 : : static int
146 : 3135 : weakref_exec(PyObject *module)
147 : : {
148 : 3135 : Py_INCREF(&_PyWeakref_RefType);
149 [ - + ]: 3135 : if (PyModule_AddObject(module, "ref", (PyObject *) &_PyWeakref_RefType) < 0) {
150 : 0 : Py_DECREF(&_PyWeakref_RefType);
151 : 0 : return -1;
152 : : }
153 : 3135 : Py_INCREF(&_PyWeakref_RefType);
154 [ - + ]: 3135 : if (PyModule_AddObject(module, "ReferenceType",
155 : : (PyObject *) &_PyWeakref_RefType) < 0) {
156 : 0 : Py_DECREF(&_PyWeakref_RefType);
157 : 0 : return -1;
158 : : }
159 : 3135 : Py_INCREF(&_PyWeakref_ProxyType);
160 [ - + ]: 3135 : if (PyModule_AddObject(module, "ProxyType",
161 : : (PyObject *) &_PyWeakref_ProxyType) < 0) {
162 : 0 : Py_DECREF(&_PyWeakref_ProxyType);
163 : 0 : return -1;
164 : : }
165 : 3135 : Py_INCREF(&_PyWeakref_CallableProxyType);
166 [ - + ]: 3135 : if (PyModule_AddObject(module, "CallableProxyType",
167 : : (PyObject *) &_PyWeakref_CallableProxyType) < 0) {
168 : 0 : Py_DECREF(&_PyWeakref_CallableProxyType);
169 : 0 : return -1;
170 : : }
171 : :
172 : 3135 : return 0;
173 : : }
174 : :
175 : : static struct PyModuleDef_Slot weakref_slots[] = {
176 : : {Py_mod_exec, weakref_exec},
177 : : {0, NULL}
178 : : };
179 : :
180 : : static struct PyModuleDef weakrefmodule = {
181 : : PyModuleDef_HEAD_INIT,
182 : : "_weakref",
183 : : "Weak-reference support module.",
184 : : 0,
185 : : weakref_functions,
186 : : weakref_slots,
187 : : NULL,
188 : : NULL,
189 : : NULL
190 : : };
191 : :
192 : : PyMODINIT_FUNC
193 : 3135 : PyInit__weakref(void)
194 : : {
195 : 3135 : return PyModuleDef_Init(&weakrefmodule);
196 : : }
|