17db96d56Sopenharmony_ci#include "Python.h" 27db96d56Sopenharmony_ci#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ci#define GET_WEAKREFS_LISTPTR(o) \ 67db96d56Sopenharmony_ci ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o)) 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ci/*[clinic input] 97db96d56Sopenharmony_cimodule _weakref 107db96d56Sopenharmony_ci[clinic start generated code]*/ 117db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ffec73b85846596d]*/ 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci#include "clinic/_weakref.c.h" 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci/*[clinic input] 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci_weakref.getweakrefcount -> Py_ssize_t 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ci object: object 207db96d56Sopenharmony_ci / 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ciReturn the number of weak references to 'object'. 237db96d56Sopenharmony_ci[clinic start generated code]*/ 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_cistatic Py_ssize_t 267db96d56Sopenharmony_ci_weakref_getweakrefcount_impl(PyObject *module, PyObject *object) 277db96d56Sopenharmony_ci/*[clinic end generated code: output=301806d59558ff3e input=cedb69711b6a2507]*/ 287db96d56Sopenharmony_ci{ 297db96d56Sopenharmony_ci PyWeakReference **list; 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) 327db96d56Sopenharmony_ci return 0; 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_ci list = GET_WEAKREFS_LISTPTR(object); 357db96d56Sopenharmony_ci return _PyWeakref_GetWeakrefCount(*list); 367db96d56Sopenharmony_ci} 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_cistatic int 407db96d56Sopenharmony_ciis_dead_weakref(PyObject *value) 417db96d56Sopenharmony_ci{ 427db96d56Sopenharmony_ci if (!PyWeakref_Check(value)) { 437db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "not a weakref"); 447db96d56Sopenharmony_ci return -1; 457db96d56Sopenharmony_ci } 467db96d56Sopenharmony_ci return PyWeakref_GET_OBJECT(value) == Py_None; 477db96d56Sopenharmony_ci} 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci/*[clinic input] 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci_weakref._remove_dead_weakref -> object 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci dct: object(subclass_of='&PyDict_Type') 547db96d56Sopenharmony_ci key: object 557db96d56Sopenharmony_ci / 567db96d56Sopenharmony_ci 577db96d56Sopenharmony_ciAtomically remove key from dict if it points to a dead weakref. 587db96d56Sopenharmony_ci[clinic start generated code]*/ 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_cistatic PyObject * 617db96d56Sopenharmony_ci_weakref__remove_dead_weakref_impl(PyObject *module, PyObject *dct, 627db96d56Sopenharmony_ci PyObject *key) 637db96d56Sopenharmony_ci/*[clinic end generated code: output=d9ff53061fcb875c input=19fc91f257f96a1d]*/ 647db96d56Sopenharmony_ci{ 657db96d56Sopenharmony_ci if (_PyDict_DelItemIf(dct, key, is_dead_weakref) < 0) { 667db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_KeyError)) 677db96d56Sopenharmony_ci /* This function is meant to allow safe weak-value dicts 687db96d56Sopenharmony_ci with GC in another thread (see issue #28427), so it's 697db96d56Sopenharmony_ci ok if the key doesn't exist anymore. 707db96d56Sopenharmony_ci */ 717db96d56Sopenharmony_ci PyErr_Clear(); 727db96d56Sopenharmony_ci else 737db96d56Sopenharmony_ci return NULL; 747db96d56Sopenharmony_ci } 757db96d56Sopenharmony_ci Py_RETURN_NONE; 767db96d56Sopenharmony_ci} 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_ci/*[clinic input] 807db96d56Sopenharmony_ci_weakref.getweakrefs 817db96d56Sopenharmony_ci object: object 827db96d56Sopenharmony_ci / 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ciReturn a list of all weak reference objects pointing to 'object'. 857db96d56Sopenharmony_ci[clinic start generated code]*/ 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_cistatic PyObject * 887db96d56Sopenharmony_ci_weakref_getweakrefs(PyObject *module, PyObject *object) 897db96d56Sopenharmony_ci/*[clinic end generated code: output=25c7731d8e011824 input=00c6d0e5d3206693]*/ 907db96d56Sopenharmony_ci{ 917db96d56Sopenharmony_ci PyObject *result = NULL; 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci if (_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { 947db96d56Sopenharmony_ci PyWeakReference **list = GET_WEAKREFS_LISTPTR(object); 957db96d56Sopenharmony_ci Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list); 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci result = PyList_New(count); 987db96d56Sopenharmony_ci if (result != NULL) { 997db96d56Sopenharmony_ci PyWeakReference *current = *list; 1007db96d56Sopenharmony_ci Py_ssize_t i; 1017db96d56Sopenharmony_ci for (i = 0; i < count; ++i) { 1027db96d56Sopenharmony_ci PyList_SET_ITEM(result, i, (PyObject *) current); 1037db96d56Sopenharmony_ci Py_INCREF(current); 1047db96d56Sopenharmony_ci current = current->wr_next; 1057db96d56Sopenharmony_ci } 1067db96d56Sopenharmony_ci } 1077db96d56Sopenharmony_ci } 1087db96d56Sopenharmony_ci else { 1097db96d56Sopenharmony_ci result = PyList_New(0); 1107db96d56Sopenharmony_ci } 1117db96d56Sopenharmony_ci return result; 1127db96d56Sopenharmony_ci} 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci/*[clinic input] 1167db96d56Sopenharmony_ci 1177db96d56Sopenharmony_ci_weakref.proxy 1187db96d56Sopenharmony_ci object: object 1197db96d56Sopenharmony_ci callback: object(c_default="NULL") = None 1207db96d56Sopenharmony_ci / 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ciCreate a proxy object that weakly references 'object'. 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci'callback', if given, is called with a reference to the 1257db96d56Sopenharmony_ciproxy when 'object' is about to be finalized. 1267db96d56Sopenharmony_ci[clinic start generated code]*/ 1277db96d56Sopenharmony_ci 1287db96d56Sopenharmony_cistatic PyObject * 1297db96d56Sopenharmony_ci_weakref_proxy_impl(PyObject *module, PyObject *object, PyObject *callback) 1307db96d56Sopenharmony_ci/*[clinic end generated code: output=d68fa4ad9ea40519 input=4808adf22fd137e7]*/ 1317db96d56Sopenharmony_ci{ 1327db96d56Sopenharmony_ci return PyWeakref_NewProxy(object, callback); 1337db96d56Sopenharmony_ci} 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_cistatic PyMethodDef 1377db96d56Sopenharmony_ciweakref_functions[] = { 1387db96d56Sopenharmony_ci _WEAKREF_GETWEAKREFCOUNT_METHODDEF 1397db96d56Sopenharmony_ci _WEAKREF__REMOVE_DEAD_WEAKREF_METHODDEF 1407db96d56Sopenharmony_ci _WEAKREF_GETWEAKREFS_METHODDEF 1417db96d56Sopenharmony_ci _WEAKREF_PROXY_METHODDEF 1427db96d56Sopenharmony_ci {NULL, NULL, 0, NULL} 1437db96d56Sopenharmony_ci}; 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_cistatic int 1467db96d56Sopenharmony_ciweakref_exec(PyObject *module) 1477db96d56Sopenharmony_ci{ 1487db96d56Sopenharmony_ci Py_INCREF(&_PyWeakref_RefType); 1497db96d56Sopenharmony_ci if (PyModule_AddObject(module, "ref", (PyObject *) &_PyWeakref_RefType) < 0) { 1507db96d56Sopenharmony_ci Py_DECREF(&_PyWeakref_RefType); 1517db96d56Sopenharmony_ci return -1; 1527db96d56Sopenharmony_ci } 1537db96d56Sopenharmony_ci Py_INCREF(&_PyWeakref_RefType); 1547db96d56Sopenharmony_ci if (PyModule_AddObject(module, "ReferenceType", 1557db96d56Sopenharmony_ci (PyObject *) &_PyWeakref_RefType) < 0) { 1567db96d56Sopenharmony_ci Py_DECREF(&_PyWeakref_RefType); 1577db96d56Sopenharmony_ci return -1; 1587db96d56Sopenharmony_ci } 1597db96d56Sopenharmony_ci Py_INCREF(&_PyWeakref_ProxyType); 1607db96d56Sopenharmony_ci if (PyModule_AddObject(module, "ProxyType", 1617db96d56Sopenharmony_ci (PyObject *) &_PyWeakref_ProxyType) < 0) { 1627db96d56Sopenharmony_ci Py_DECREF(&_PyWeakref_ProxyType); 1637db96d56Sopenharmony_ci return -1; 1647db96d56Sopenharmony_ci } 1657db96d56Sopenharmony_ci Py_INCREF(&_PyWeakref_CallableProxyType); 1667db96d56Sopenharmony_ci if (PyModule_AddObject(module, "CallableProxyType", 1677db96d56Sopenharmony_ci (PyObject *) &_PyWeakref_CallableProxyType) < 0) { 1687db96d56Sopenharmony_ci Py_DECREF(&_PyWeakref_CallableProxyType); 1697db96d56Sopenharmony_ci return -1; 1707db96d56Sopenharmony_ci } 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_ci return 0; 1737db96d56Sopenharmony_ci} 1747db96d56Sopenharmony_ci 1757db96d56Sopenharmony_cistatic struct PyModuleDef_Slot weakref_slots[] = { 1767db96d56Sopenharmony_ci {Py_mod_exec, weakref_exec}, 1777db96d56Sopenharmony_ci {0, NULL} 1787db96d56Sopenharmony_ci}; 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_cistatic struct PyModuleDef weakrefmodule = { 1817db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 1827db96d56Sopenharmony_ci "_weakref", 1837db96d56Sopenharmony_ci "Weak-reference support module.", 1847db96d56Sopenharmony_ci 0, 1857db96d56Sopenharmony_ci weakref_functions, 1867db96d56Sopenharmony_ci weakref_slots, 1877db96d56Sopenharmony_ci NULL, 1887db96d56Sopenharmony_ci NULL, 1897db96d56Sopenharmony_ci NULL 1907db96d56Sopenharmony_ci}; 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_ciPyMODINIT_FUNC 1937db96d56Sopenharmony_ciPyInit__weakref(void) 1947db96d56Sopenharmony_ci{ 1957db96d56Sopenharmony_ci return PyModuleDef_Init(&weakrefmodule); 1967db96d56Sopenharmony_ci} 197