diff options
author | nkozlovskiy <nmk@ydb.tech> | 2023-09-29 12:24:06 +0300 |
---|---|---|
committer | nkozlovskiy <nmk@ydb.tech> | 2023-09-29 12:41:34 +0300 |
commit | e0e3e1717e3d33762ce61950504f9637a6e669ed (patch) | |
tree | bca3ff6939b10ed60c3d5c12439963a1146b9711 /contrib/tools/python/src/Modules/_weakref.c | |
parent | 38f2c5852db84c7b4d83adfcb009eb61541d1ccd (diff) | |
download | ydb-e0e3e1717e3d33762ce61950504f9637a6e669ed.tar.gz |
add ydb deps
Diffstat (limited to 'contrib/tools/python/src/Modules/_weakref.c')
-rw-r--r-- | contrib/tools/python/src/Modules/_weakref.c | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/contrib/tools/python/src/Modules/_weakref.c b/contrib/tools/python/src/Modules/_weakref.c new file mode 100644 index 0000000000..46e00638be --- /dev/null +++ b/contrib/tools/python/src/Modules/_weakref.c @@ -0,0 +1,151 @@ +#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); + } +} |