| #include "Python.h" | 
 |  | 
 |  | 
 | #define GET_WEAKREFS_LISTPTR(o) \ | 
 |         ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o)) | 
 |  | 
 |  | 
 | static int | 
 | is_dead_weakref(PyObject *value) | 
 | { | 
 |     if (!PyWeakref_Check(value)) { | 
 |         PyErr_SetString(PyExc_TypeError, "not a weakref"); | 
 |         return -1; | 
 |     } | 
 |     return PyWeakref_GET_OBJECT(value) == Py_None; | 
 | } | 
 |  | 
 | PyDoc_STRVAR(remove_dead_weakref__doc__, | 
 | "_remove_dead_weakref(dict, key) -- atomically remove key from dict\n" | 
 | "if it points to a dead weakref."); | 
 |  | 
 | static PyObject * | 
 | remove_dead_weakref(PyObject *self, PyObject *args) | 
 | { | 
 |     PyObject *dct, *key; | 
 |  | 
 |     if (!PyArg_ParseTuple(args, "O!O:_remove_dead_weakref", | 
 |                           &PyDict_Type, &dct, &key)) { | 
 |         return NULL; | 
 |     } | 
 |     if (_PyDict_DelItemIf(dct, key, is_dead_weakref) < 0) { | 
 |         if (PyErr_ExceptionMatches(PyExc_KeyError)) | 
 |             /* This function is meant to allow safe weak-value dicts | 
 |                with GC in another thread (see issue #28427), so it's | 
 |                ok if the key doesn't exist anymore. | 
 |                */ | 
 |             PyErr_Clear(); | 
 |         else | 
 |             return NULL; | 
 |     } | 
 |     Py_RETURN_NONE; | 
 | } | 
 |  | 
 |  | 
 | PyDoc_STRVAR(weakref_getweakrefcount__doc__, | 
 | "getweakrefcount(object) -- return the number of weak references\n" | 
 | "to 'object'."); | 
 |  | 
 | static PyObject * | 
 | weakref_getweakrefcount(PyObject *self, PyObject *object) | 
 | { | 
 |     PyObject *result = NULL; | 
 |  | 
 |     if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { | 
 |         PyWeakReference **list = GET_WEAKREFS_LISTPTR(object); | 
 |  | 
 |         result = PyInt_FromSsize_t(_PyWeakref_GetWeakrefCount(*list)); | 
 |     } | 
 |     else | 
 |         result = PyInt_FromLong(0); | 
 |  | 
 |     return result; | 
 | } | 
 |  | 
 |  | 
 | PyDoc_STRVAR(weakref_getweakrefs__doc__, | 
 | "getweakrefs(object) -- return a list of all weak reference objects\n" | 
 | "that point to 'object'."); | 
 |  | 
 | static PyObject * | 
 | weakref_getweakrefs(PyObject *self, PyObject *object) | 
 | { | 
 |     PyObject *result = NULL; | 
 |  | 
 |     if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { | 
 |         PyWeakReference **list = GET_WEAKREFS_LISTPTR(object); | 
 |         Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list); | 
 |  | 
 |         result = PyList_New(count); | 
 |         if (result != NULL) { | 
 |             PyWeakReference *current = *list; | 
 |             Py_ssize_t i; | 
 |             for (i = 0; i < count; ++i) { | 
 |                 PyList_SET_ITEM(result, i, (PyObject *) current); | 
 |                 Py_INCREF(current); | 
 |                 current = current->wr_next; | 
 |             } | 
 |         } | 
 |     } | 
 |     else { | 
 |         result = PyList_New(0); | 
 |     } | 
 |     return result; | 
 | } | 
 |  | 
 |  | 
 | PyDoc_STRVAR(weakref_proxy__doc__, | 
 | "proxy(object[, callback]) -- create a proxy object that weakly\n" | 
 | "references 'object'.  'callback', if given, is called with a\n" | 
 | "reference to the proxy when 'object' is about to be finalized."); | 
 |  | 
 | static PyObject * | 
 | weakref_proxy(PyObject *self, PyObject *args) | 
 | { | 
 |     PyObject *object; | 
 |     PyObject *callback = NULL; | 
 |     PyObject *result = NULL; | 
 |  | 
 |     if (PyArg_UnpackTuple(args, "proxy", 1, 2, &object, &callback)) { | 
 |         result = PyWeakref_NewProxy(object, callback); | 
 |     } | 
 |     return result; | 
 | } | 
 |  | 
 |  | 
 | static PyMethodDef | 
 | weakref_functions[] =  { | 
 |     {"getweakrefcount", weakref_getweakrefcount,        METH_O, | 
 |      weakref_getweakrefcount__doc__}, | 
 |     {"getweakrefs",     weakref_getweakrefs,            METH_O, | 
 |      weakref_getweakrefs__doc__}, | 
 |     {"proxy",           weakref_proxy,                  METH_VARARGS, | 
 |      weakref_proxy__doc__}, | 
 |     {"_remove_dead_weakref", remove_dead_weakref,       METH_VARARGS, | 
 |      remove_dead_weakref__doc__}, | 
 |     {NULL, NULL, 0, NULL} | 
 | }; | 
 |  | 
 |  | 
 | PyMODINIT_FUNC | 
 | init_weakref(void) | 
 | { | 
 |     PyObject *m; | 
 |  | 
 |     m = Py_InitModule3("_weakref", weakref_functions, | 
 |                        "Weak-reference support module."); | 
 |     if (m != NULL) { | 
 |         Py_INCREF(&_PyWeakref_RefType); | 
 |         PyModule_AddObject(m, "ref", | 
 |                            (PyObject *) &_PyWeakref_RefType); | 
 |         Py_INCREF(&_PyWeakref_RefType); | 
 |         PyModule_AddObject(m, "ReferenceType", | 
 |                            (PyObject *) &_PyWeakref_RefType); | 
 |         Py_INCREF(&_PyWeakref_ProxyType); | 
 |         PyModule_AddObject(m, "ProxyType", | 
 |                            (PyObject *) &_PyWeakref_ProxyType); | 
 |         Py_INCREF(&_PyWeakref_CallableProxyType); | 
 |         PyModule_AddObject(m, "CallableProxyType", | 
 |                            (PyObject *) &_PyWeakref_CallableProxyType); | 
 |     } | 
 | } |