diff options
Diffstat (limited to 'contrib/tools/python3/Modules/_weakref.c')
| -rw-r--r-- | contrib/tools/python3/Modules/_weakref.c | 88 |
1 files changed, 39 insertions, 49 deletions
diff --git a/contrib/tools/python3/Modules/_weakref.c b/contrib/tools/python3/Modules/_weakref.c index 387b8fa9d0a..ecaa08ff60f 100644 --- a/contrib/tools/python3/Modules/_weakref.c +++ b/contrib/tools/python3/Modules/_weakref.c @@ -1,6 +1,7 @@ #include "Python.h" -#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR - +#include "pycore_dict.h" // _PyDict_DelItemIf() +#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR() +#include "pycore_weakref.h" // _PyWeakref_IS_DEAD() #define GET_WEAKREFS_LISTPTR(o) \ ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o)) @@ -13,7 +14,6 @@ module _weakref #include "clinic/_weakref.c.h" /*[clinic input] - _weakref.getweakrefcount -> Py_ssize_t object: object @@ -24,26 +24,20 @@ Return the number of weak references to 'object'. static Py_ssize_t _weakref_getweakrefcount_impl(PyObject *module, PyObject *object) -/*[clinic end generated code: output=301806d59558ff3e input=cedb69711b6a2507]*/ +/*[clinic end generated code: output=301806d59558ff3e input=7d4d04fcaccf64d5]*/ { - PyWeakReference **list; - - if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) - return 0; - - list = GET_WEAKREFS_LISTPTR(object); - return _PyWeakref_GetWeakrefCount(*list); + return _PyWeakref_GetWeakrefCount(object); } static int -is_dead_weakref(PyObject *value) +is_dead_weakref(PyObject *value, void *unused) { if (!PyWeakref_Check(value)) { PyErr_SetString(PyExc_TypeError, "not a weakref"); return -1; } - return PyWeakref_GET_OBJECT(value) == Py_None; + return _PyWeakref_IS_DEAD(value); } /*[clinic input] @@ -62,15 +56,8 @@ _weakref__remove_dead_weakref_impl(PyObject *module, PyObject *dct, PyObject *key) /*[clinic end generated code: output=d9ff53061fcb875c input=19fc91f257f96a1d]*/ { - 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; + if (_PyDict_DelItemIf(dct, key, is_dead_weakref, NULL) < 0) { + return NULL; } Py_RETURN_NONE; } @@ -88,26 +75,36 @@ static PyObject * _weakref_getweakrefs(PyObject *module, PyObject *object) /*[clinic end generated code: output=25c7731d8e011824 input=00c6d0e5d3206693]*/ { - PyObject *result = NULL; + if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { + return PyList_New(0); + } - if (_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { - PyWeakReference **list = GET_WEAKREFS_LISTPTR(object); - Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list); + PyObject *result = PyList_New(0); + if (result == NULL) { + return NULL; + } - 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; + LOCK_WEAKREFS(object); + PyWeakReference *current = *GET_WEAKREFS_LISTPTR(object); + while (current != NULL) { + PyObject *curobj = (PyObject *) current; + if (_Py_TryIncref(curobj)) { + if (PyList_Append(result, curobj)) { + UNLOCK_WEAKREFS(object); + Py_DECREF(curobj); + Py_DECREF(result); + return NULL; + } + else { + // Undo our _Py_TryIncref. This is safe to do with the lock + // held in free-threaded builds; the list holds a reference to + // curobj so we're guaranteed not to invoke the destructor. + Py_DECREF(curobj); } } + current = current->wr_next; } - else { - result = PyList_New(0); - } + UNLOCK_WEAKREFS(object); return result; } @@ -145,27 +142,19 @@ weakref_functions[] = { static int weakref_exec(PyObject *module) { - Py_INCREF(&_PyWeakref_RefType); - if (PyModule_AddObject(module, "ref", (PyObject *) &_PyWeakref_RefType) < 0) { - Py_DECREF(&_PyWeakref_RefType); + if (PyModule_AddObjectRef(module, "ref", (PyObject *) &_PyWeakref_RefType) < 0) { return -1; } - Py_INCREF(&_PyWeakref_RefType); - if (PyModule_AddObject(module, "ReferenceType", + if (PyModule_AddObjectRef(module, "ReferenceType", (PyObject *) &_PyWeakref_RefType) < 0) { - Py_DECREF(&_PyWeakref_RefType); return -1; } - Py_INCREF(&_PyWeakref_ProxyType); - if (PyModule_AddObject(module, "ProxyType", + if (PyModule_AddObjectRef(module, "ProxyType", (PyObject *) &_PyWeakref_ProxyType) < 0) { - Py_DECREF(&_PyWeakref_ProxyType); return -1; } - Py_INCREF(&_PyWeakref_CallableProxyType); - if (PyModule_AddObject(module, "CallableProxyType", + if (PyModule_AddObjectRef(module, "CallableProxyType", (PyObject *) &_PyWeakref_CallableProxyType) < 0) { - Py_DECREF(&_PyWeakref_CallableProxyType); return -1; } @@ -175,6 +164,7 @@ weakref_exec(PyObject *module) static struct PyModuleDef_Slot weakref_slots[] = { {Py_mod_exec, weakref_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL} }; |
