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