1 #include "Python.h" 2 3 4 #define GET_WEAKREFS_LISTPTR(o) \ 5 ((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 { 28 PyWeakReference **list; 29 30 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) 31 return 0; 32 33 list = GET_WEAKREFS_LISTPTR(object); 34 return _PyWeakref_GetWeakrefCount(*list); 35 } 36 37 38 static int 39 is_dead_weakref(PyObject *value) 40 { 41 if (!PyWeakref_Check(value)) { 42 PyErr_SetString(PyExc_TypeError, "not a weakref"); 43 return -1; 44 } 45 return PyWeakref_GET_OBJECT(value) == Py_None; 46 } 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 { 64 if (_PyDict_DelItemIf(dct, key, is_dead_weakref) < 0) { 65 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 PyErr_Clear(); 71 else 72 return NULL; 73 } 74 Py_RETURN_NONE; 75 } 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 { 85 PyObject *result = NULL; 86 87 if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { 88 PyWeakReference **list = GET_WEAKREFS_LISTPTR(object); 89 Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list); 90 91 result = PyList_New(count); 92 if (result != NULL) { 93 PyWeakReference *current = *list; 94 Py_ssize_t i; 95 for (i = 0; i < count; ++i) { 96 PyList_SET_ITEM(result, i, (PyObject *) current); 97 Py_INCREF(current); 98 current = current->wr_next; 99 } 100 } 101 } 102 else { 103 result = PyList_New(0); 104 } 105 return result; 106 } 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 { 117 PyObject *object; 118 PyObject *callback = NULL; 119 PyObject *result = NULL; 120 121 if (PyArg_UnpackTuple(args, "proxy", 1, 2, &object, &callback)) { 122 result = PyWeakref_NewProxy(object, callback); 123 } 124 return result; 125 } 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 { 155 PyObject *m; 156 157 m = PyModule_Create(&weakrefmodule); 158 159 if (m != NULL) { 160 Py_INCREF(&_PyWeakref_RefType); 161 PyModule_AddObject(m, "ref", 162 (PyObject *) &_PyWeakref_RefType); 163 Py_INCREF(&_PyWeakref_RefType); 164 PyModule_AddObject(m, "ReferenceType", 165 (PyObject *) &_PyWeakref_RefType); 166 Py_INCREF(&_PyWeakref_ProxyType); 167 PyModule_AddObject(m, "ProxyType", 168 (PyObject *) &_PyWeakref_ProxyType); 169 Py_INCREF(&_PyWeakref_CallableProxyType); 170 PyModule_AddObject(m, "CallableProxyType", 171 (PyObject *) &_PyWeakref_CallableProxyType); 172 } 173 return m; 174 } 175