17db96d56Sopenharmony_ci#include "Python.h" 27db96d56Sopenharmony_ci#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR() 37db96d56Sopenharmony_ci#include "structmember.h" // PyMemberDef 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ci#define GET_WEAKREFS_LISTPTR(o) \ 77db96d56Sopenharmony_ci ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o)) 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ciPy_ssize_t 117db96d56Sopenharmony_ci_PyWeakref_GetWeakrefCount(PyWeakReference *head) 127db96d56Sopenharmony_ci{ 137db96d56Sopenharmony_ci Py_ssize_t count = 0; 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci while (head != NULL) { 167db96d56Sopenharmony_ci ++count; 177db96d56Sopenharmony_ci head = head->wr_next; 187db96d56Sopenharmony_ci } 197db96d56Sopenharmony_ci return count; 207db96d56Sopenharmony_ci} 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_cistatic PyObject *weakref_vectorcall(PyWeakReference *self, PyObject *const *args, size_t nargsf, PyObject *kwnames); 237db96d56Sopenharmony_ci 247db96d56Sopenharmony_cistatic void 257db96d56Sopenharmony_ciinit_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback) 267db96d56Sopenharmony_ci{ 277db96d56Sopenharmony_ci self->hash = -1; 287db96d56Sopenharmony_ci self->wr_object = ob; 297db96d56Sopenharmony_ci self->wr_prev = NULL; 307db96d56Sopenharmony_ci self->wr_next = NULL; 317db96d56Sopenharmony_ci self->wr_callback = Py_XNewRef(callback); 327db96d56Sopenharmony_ci self->vectorcall = (vectorcallfunc)weakref_vectorcall; 337db96d56Sopenharmony_ci} 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_cistatic PyWeakReference * 367db96d56Sopenharmony_cinew_weakref(PyObject *ob, PyObject *callback) 377db96d56Sopenharmony_ci{ 387db96d56Sopenharmony_ci PyWeakReference *result; 397db96d56Sopenharmony_ci 407db96d56Sopenharmony_ci result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType); 417db96d56Sopenharmony_ci if (result) { 427db96d56Sopenharmony_ci init_weakref(result, ob, callback); 437db96d56Sopenharmony_ci PyObject_GC_Track(result); 447db96d56Sopenharmony_ci } 457db96d56Sopenharmony_ci return result; 467db96d56Sopenharmony_ci} 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci/* This function clears the passed-in reference and removes it from the 507db96d56Sopenharmony_ci * list of weak references for the referent. This is the only code that 517db96d56Sopenharmony_ci * removes an item from the doubly-linked list of weak references for an 527db96d56Sopenharmony_ci * object; it is also responsible for clearing the callback slot. 537db96d56Sopenharmony_ci */ 547db96d56Sopenharmony_cistatic void 557db96d56Sopenharmony_ciclear_weakref(PyWeakReference *self) 567db96d56Sopenharmony_ci{ 577db96d56Sopenharmony_ci PyObject *callback = self->wr_callback; 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ci if (self->wr_object != Py_None) { 607db96d56Sopenharmony_ci PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object); 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_ci if (*list == self) 637db96d56Sopenharmony_ci /* If 'self' is the end of the list (and thus self->wr_next == NULL) 647db96d56Sopenharmony_ci then the weakref list itself (and thus the value of *list) will 657db96d56Sopenharmony_ci end up being set to NULL. */ 667db96d56Sopenharmony_ci *list = self->wr_next; 677db96d56Sopenharmony_ci self->wr_object = Py_None; 687db96d56Sopenharmony_ci if (self->wr_prev != NULL) 697db96d56Sopenharmony_ci self->wr_prev->wr_next = self->wr_next; 707db96d56Sopenharmony_ci if (self->wr_next != NULL) 717db96d56Sopenharmony_ci self->wr_next->wr_prev = self->wr_prev; 727db96d56Sopenharmony_ci self->wr_prev = NULL; 737db96d56Sopenharmony_ci self->wr_next = NULL; 747db96d56Sopenharmony_ci } 757db96d56Sopenharmony_ci if (callback != NULL) { 767db96d56Sopenharmony_ci Py_DECREF(callback); 777db96d56Sopenharmony_ci self->wr_callback = NULL; 787db96d56Sopenharmony_ci } 797db96d56Sopenharmony_ci} 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci/* Cyclic gc uses this to *just* clear the passed-in reference, leaving 827db96d56Sopenharmony_ci * the callback intact and uncalled. It must be possible to call self's 837db96d56Sopenharmony_ci * tp_dealloc() after calling this, so self has to be left in a sane enough 847db96d56Sopenharmony_ci * state for that to work. We expect tp_dealloc to decref the callback 857db96d56Sopenharmony_ci * then. The reason for not letting clear_weakref() decref the callback 867db96d56Sopenharmony_ci * right now is that if the callback goes away, that may in turn trigger 877db96d56Sopenharmony_ci * another callback (if a weak reference to the callback exists) -- running 887db96d56Sopenharmony_ci * arbitrary Python code in the middle of gc is a disaster. The convolution 897db96d56Sopenharmony_ci * here allows gc to delay triggering such callbacks until the world is in 907db96d56Sopenharmony_ci * a sane state again. 917db96d56Sopenharmony_ci */ 927db96d56Sopenharmony_civoid 937db96d56Sopenharmony_ci_PyWeakref_ClearRef(PyWeakReference *self) 947db96d56Sopenharmony_ci{ 957db96d56Sopenharmony_ci PyObject *callback; 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci assert(self != NULL); 987db96d56Sopenharmony_ci assert(PyWeakref_Check(self)); 997db96d56Sopenharmony_ci /* Preserve and restore the callback around clear_weakref. */ 1007db96d56Sopenharmony_ci callback = self->wr_callback; 1017db96d56Sopenharmony_ci self->wr_callback = NULL; 1027db96d56Sopenharmony_ci clear_weakref(self); 1037db96d56Sopenharmony_ci self->wr_callback = callback; 1047db96d56Sopenharmony_ci} 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_cistatic void 1077db96d56Sopenharmony_ciweakref_dealloc(PyObject *self) 1087db96d56Sopenharmony_ci{ 1097db96d56Sopenharmony_ci PyObject_GC_UnTrack(self); 1107db96d56Sopenharmony_ci clear_weakref((PyWeakReference *) self); 1117db96d56Sopenharmony_ci Py_TYPE(self)->tp_free(self); 1127db96d56Sopenharmony_ci} 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_cistatic int 1167db96d56Sopenharmony_cigc_traverse(PyWeakReference *self, visitproc visit, void *arg) 1177db96d56Sopenharmony_ci{ 1187db96d56Sopenharmony_ci Py_VISIT(self->wr_callback); 1197db96d56Sopenharmony_ci return 0; 1207db96d56Sopenharmony_ci} 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_cistatic int 1247db96d56Sopenharmony_cigc_clear(PyWeakReference *self) 1257db96d56Sopenharmony_ci{ 1267db96d56Sopenharmony_ci clear_weakref(self); 1277db96d56Sopenharmony_ci return 0; 1287db96d56Sopenharmony_ci} 1297db96d56Sopenharmony_ci 1307db96d56Sopenharmony_ci 1317db96d56Sopenharmony_cistatic PyObject * 1327db96d56Sopenharmony_ciweakref_vectorcall(PyWeakReference *self, PyObject *const *args, 1337db96d56Sopenharmony_ci size_t nargsf, PyObject *kwnames) 1347db96d56Sopenharmony_ci{ 1357db96d56Sopenharmony_ci if (!_PyArg_NoKwnames("weakref", kwnames)) { 1367db96d56Sopenharmony_ci return NULL; 1377db96d56Sopenharmony_ci } 1387db96d56Sopenharmony_ci Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); 1397db96d56Sopenharmony_ci if (!_PyArg_CheckPositional("weakref", nargs, 0, 0)) { 1407db96d56Sopenharmony_ci return NULL; 1417db96d56Sopenharmony_ci } 1427db96d56Sopenharmony_ci return Py_NewRef(PyWeakref_GET_OBJECT(self)); 1437db96d56Sopenharmony_ci} 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_cistatic Py_hash_t 1467db96d56Sopenharmony_ciweakref_hash(PyWeakReference *self) 1477db96d56Sopenharmony_ci{ 1487db96d56Sopenharmony_ci if (self->hash != -1) 1497db96d56Sopenharmony_ci return self->hash; 1507db96d56Sopenharmony_ci PyObject* obj = PyWeakref_GET_OBJECT(self); 1517db96d56Sopenharmony_ci if (obj == Py_None) { 1527db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "weak object has gone away"); 1537db96d56Sopenharmony_ci return -1; 1547db96d56Sopenharmony_ci } 1557db96d56Sopenharmony_ci Py_INCREF(obj); 1567db96d56Sopenharmony_ci self->hash = PyObject_Hash(obj); 1577db96d56Sopenharmony_ci Py_DECREF(obj); 1587db96d56Sopenharmony_ci return self->hash; 1597db96d56Sopenharmony_ci} 1607db96d56Sopenharmony_ci 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_cistatic PyObject * 1637db96d56Sopenharmony_ciweakref_repr(PyWeakReference *self) 1647db96d56Sopenharmony_ci{ 1657db96d56Sopenharmony_ci PyObject *name, *repr; 1667db96d56Sopenharmony_ci PyObject* obj = PyWeakref_GET_OBJECT(self); 1677db96d56Sopenharmony_ci 1687db96d56Sopenharmony_ci if (obj == Py_None) { 1697db96d56Sopenharmony_ci return PyUnicode_FromFormat("<weakref at %p; dead>", self); 1707db96d56Sopenharmony_ci } 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_ci Py_INCREF(obj); 1737db96d56Sopenharmony_ci name = _PyObject_LookupSpecial(obj, &_Py_ID(__name__)); 1747db96d56Sopenharmony_ci if (name == NULL || !PyUnicode_Check(name)) { 1757db96d56Sopenharmony_ci repr = PyUnicode_FromFormat( 1767db96d56Sopenharmony_ci "<weakref at %p; to '%s' at %p>", 1777db96d56Sopenharmony_ci self, 1787db96d56Sopenharmony_ci Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name, 1797db96d56Sopenharmony_ci obj); 1807db96d56Sopenharmony_ci } 1817db96d56Sopenharmony_ci else { 1827db96d56Sopenharmony_ci repr = PyUnicode_FromFormat( 1837db96d56Sopenharmony_ci "<weakref at %p; to '%s' at %p (%U)>", 1847db96d56Sopenharmony_ci self, 1857db96d56Sopenharmony_ci Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name, 1867db96d56Sopenharmony_ci obj, 1877db96d56Sopenharmony_ci name); 1887db96d56Sopenharmony_ci } 1897db96d56Sopenharmony_ci Py_DECREF(obj); 1907db96d56Sopenharmony_ci Py_XDECREF(name); 1917db96d56Sopenharmony_ci return repr; 1927db96d56Sopenharmony_ci} 1937db96d56Sopenharmony_ci 1947db96d56Sopenharmony_ci/* Weak references only support equality, not ordering. Two weak references 1957db96d56Sopenharmony_ci are equal if the underlying objects are equal. If the underlying object has 1967db96d56Sopenharmony_ci gone away, they are equal if they are identical. */ 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_cistatic PyObject * 1997db96d56Sopenharmony_ciweakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op) 2007db96d56Sopenharmony_ci{ 2017db96d56Sopenharmony_ci if ((op != Py_EQ && op != Py_NE) || 2027db96d56Sopenharmony_ci !PyWeakref_Check(self) || 2037db96d56Sopenharmony_ci !PyWeakref_Check(other)) { 2047db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 2057db96d56Sopenharmony_ci } 2067db96d56Sopenharmony_ci if (PyWeakref_GET_OBJECT(self) == Py_None 2077db96d56Sopenharmony_ci || PyWeakref_GET_OBJECT(other) == Py_None) { 2087db96d56Sopenharmony_ci int res = (self == other); 2097db96d56Sopenharmony_ci if (op == Py_NE) 2107db96d56Sopenharmony_ci res = !res; 2117db96d56Sopenharmony_ci if (res) 2127db96d56Sopenharmony_ci Py_RETURN_TRUE; 2137db96d56Sopenharmony_ci else 2147db96d56Sopenharmony_ci Py_RETURN_FALSE; 2157db96d56Sopenharmony_ci } 2167db96d56Sopenharmony_ci PyObject* obj = PyWeakref_GET_OBJECT(self); 2177db96d56Sopenharmony_ci PyObject* other_obj = PyWeakref_GET_OBJECT(other); 2187db96d56Sopenharmony_ci Py_INCREF(obj); 2197db96d56Sopenharmony_ci Py_INCREF(other_obj); 2207db96d56Sopenharmony_ci PyObject* res = PyObject_RichCompare(obj, other_obj, op); 2217db96d56Sopenharmony_ci Py_DECREF(obj); 2227db96d56Sopenharmony_ci Py_DECREF(other_obj); 2237db96d56Sopenharmony_ci return res; 2247db96d56Sopenharmony_ci} 2257db96d56Sopenharmony_ci 2267db96d56Sopenharmony_ci/* Given the head of an object's list of weak references, extract the 2277db96d56Sopenharmony_ci * two callback-less refs (ref and proxy). Used to determine if the 2287db96d56Sopenharmony_ci * shared references exist and to determine the back link for newly 2297db96d56Sopenharmony_ci * inserted references. 2307db96d56Sopenharmony_ci */ 2317db96d56Sopenharmony_cistatic void 2327db96d56Sopenharmony_ciget_basic_refs(PyWeakReference *head, 2337db96d56Sopenharmony_ci PyWeakReference **refp, PyWeakReference **proxyp) 2347db96d56Sopenharmony_ci{ 2357db96d56Sopenharmony_ci *refp = NULL; 2367db96d56Sopenharmony_ci *proxyp = NULL; 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ci if (head != NULL && head->wr_callback == NULL) { 2397db96d56Sopenharmony_ci /* We need to be careful that the "basic refs" aren't 2407db96d56Sopenharmony_ci subclasses of the main types. That complicates this a 2417db96d56Sopenharmony_ci little. */ 2427db96d56Sopenharmony_ci if (PyWeakref_CheckRefExact(head)) { 2437db96d56Sopenharmony_ci *refp = head; 2447db96d56Sopenharmony_ci head = head->wr_next; 2457db96d56Sopenharmony_ci } 2467db96d56Sopenharmony_ci if (head != NULL 2477db96d56Sopenharmony_ci && head->wr_callback == NULL 2487db96d56Sopenharmony_ci && PyWeakref_CheckProxy(head)) { 2497db96d56Sopenharmony_ci *proxyp = head; 2507db96d56Sopenharmony_ci /* head = head->wr_next; */ 2517db96d56Sopenharmony_ci } 2527db96d56Sopenharmony_ci } 2537db96d56Sopenharmony_ci} 2547db96d56Sopenharmony_ci 2557db96d56Sopenharmony_ci/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */ 2567db96d56Sopenharmony_cistatic void 2577db96d56Sopenharmony_ciinsert_after(PyWeakReference *newref, PyWeakReference *prev) 2587db96d56Sopenharmony_ci{ 2597db96d56Sopenharmony_ci newref->wr_prev = prev; 2607db96d56Sopenharmony_ci newref->wr_next = prev->wr_next; 2617db96d56Sopenharmony_ci if (prev->wr_next != NULL) 2627db96d56Sopenharmony_ci prev->wr_next->wr_prev = newref; 2637db96d56Sopenharmony_ci prev->wr_next = newref; 2647db96d56Sopenharmony_ci} 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_ci/* Insert 'newref' at the head of the list; 'list' points to the variable 2677db96d56Sopenharmony_ci * that stores the head. 2687db96d56Sopenharmony_ci */ 2697db96d56Sopenharmony_cistatic void 2707db96d56Sopenharmony_ciinsert_head(PyWeakReference *newref, PyWeakReference **list) 2717db96d56Sopenharmony_ci{ 2727db96d56Sopenharmony_ci PyWeakReference *next = *list; 2737db96d56Sopenharmony_ci 2747db96d56Sopenharmony_ci newref->wr_prev = NULL; 2757db96d56Sopenharmony_ci newref->wr_next = next; 2767db96d56Sopenharmony_ci if (next != NULL) 2777db96d56Sopenharmony_ci next->wr_prev = newref; 2787db96d56Sopenharmony_ci *list = newref; 2797db96d56Sopenharmony_ci} 2807db96d56Sopenharmony_ci 2817db96d56Sopenharmony_cistatic int 2827db96d56Sopenharmony_ciparse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs, 2837db96d56Sopenharmony_ci PyObject **obp, PyObject **callbackp) 2847db96d56Sopenharmony_ci{ 2857db96d56Sopenharmony_ci return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp); 2867db96d56Sopenharmony_ci} 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_cistatic PyObject * 2897db96d56Sopenharmony_ciweakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs) 2907db96d56Sopenharmony_ci{ 2917db96d56Sopenharmony_ci PyWeakReference *self = NULL; 2927db96d56Sopenharmony_ci PyObject *ob, *callback = NULL; 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ci if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) { 2957db96d56Sopenharmony_ci PyWeakReference *ref, *proxy; 2967db96d56Sopenharmony_ci PyWeakReference **list; 2977db96d56Sopenharmony_ci 2987db96d56Sopenharmony_ci if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { 2997db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 3007db96d56Sopenharmony_ci "cannot create weak reference to '%s' object", 3017db96d56Sopenharmony_ci Py_TYPE(ob)->tp_name); 3027db96d56Sopenharmony_ci return NULL; 3037db96d56Sopenharmony_ci } 3047db96d56Sopenharmony_ci if (callback == Py_None) 3057db96d56Sopenharmony_ci callback = NULL; 3067db96d56Sopenharmony_ci list = GET_WEAKREFS_LISTPTR(ob); 3077db96d56Sopenharmony_ci get_basic_refs(*list, &ref, &proxy); 3087db96d56Sopenharmony_ci if (callback == NULL && type == &_PyWeakref_RefType) { 3097db96d56Sopenharmony_ci if (ref != NULL) { 3107db96d56Sopenharmony_ci /* We can re-use an existing reference. */ 3117db96d56Sopenharmony_ci Py_INCREF(ref); 3127db96d56Sopenharmony_ci return (PyObject *)ref; 3137db96d56Sopenharmony_ci } 3147db96d56Sopenharmony_ci } 3157db96d56Sopenharmony_ci /* We have to create a new reference. */ 3167db96d56Sopenharmony_ci /* Note: the tp_alloc() can trigger cyclic GC, so the weakref 3177db96d56Sopenharmony_ci list on ob can be mutated. This means that the ref and 3187db96d56Sopenharmony_ci proxy pointers we got back earlier may have been collected, 3197db96d56Sopenharmony_ci so we need to compute these values again before we use 3207db96d56Sopenharmony_ci them. */ 3217db96d56Sopenharmony_ci self = (PyWeakReference *) (type->tp_alloc(type, 0)); 3227db96d56Sopenharmony_ci if (self != NULL) { 3237db96d56Sopenharmony_ci init_weakref(self, ob, callback); 3247db96d56Sopenharmony_ci if (callback == NULL && type == &_PyWeakref_RefType) { 3257db96d56Sopenharmony_ci insert_head(self, list); 3267db96d56Sopenharmony_ci } 3277db96d56Sopenharmony_ci else { 3287db96d56Sopenharmony_ci PyWeakReference *prev; 3297db96d56Sopenharmony_ci 3307db96d56Sopenharmony_ci get_basic_refs(*list, &ref, &proxy); 3317db96d56Sopenharmony_ci prev = (proxy == NULL) ? ref : proxy; 3327db96d56Sopenharmony_ci if (prev == NULL) 3337db96d56Sopenharmony_ci insert_head(self, list); 3347db96d56Sopenharmony_ci else 3357db96d56Sopenharmony_ci insert_after(self, prev); 3367db96d56Sopenharmony_ci } 3377db96d56Sopenharmony_ci } 3387db96d56Sopenharmony_ci } 3397db96d56Sopenharmony_ci return (PyObject *)self; 3407db96d56Sopenharmony_ci} 3417db96d56Sopenharmony_ci 3427db96d56Sopenharmony_cistatic int 3437db96d56Sopenharmony_ciweakref___init__(PyObject *self, PyObject *args, PyObject *kwargs) 3447db96d56Sopenharmony_ci{ 3457db96d56Sopenharmony_ci PyObject *tmp; 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_ci if (!_PyArg_NoKeywords("ref", kwargs)) 3487db96d56Sopenharmony_ci return -1; 3497db96d56Sopenharmony_ci 3507db96d56Sopenharmony_ci if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp)) 3517db96d56Sopenharmony_ci return 0; 3527db96d56Sopenharmony_ci else 3537db96d56Sopenharmony_ci return -1; 3547db96d56Sopenharmony_ci} 3557db96d56Sopenharmony_ci 3567db96d56Sopenharmony_ci 3577db96d56Sopenharmony_cistatic PyMemberDef weakref_members[] = { 3587db96d56Sopenharmony_ci {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY}, 3597db96d56Sopenharmony_ci {NULL} /* Sentinel */ 3607db96d56Sopenharmony_ci}; 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_cistatic PyMethodDef weakref_methods[] = { 3637db96d56Sopenharmony_ci {"__class_getitem__", Py_GenericAlias, 3647db96d56Sopenharmony_ci METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, 3657db96d56Sopenharmony_ci {NULL} /* Sentinel */ 3667db96d56Sopenharmony_ci}; 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ciPyTypeObject 3697db96d56Sopenharmony_ci_PyWeakref_RefType = { 3707db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(&PyType_Type, 0) 3717db96d56Sopenharmony_ci .tp_name = "weakref.ReferenceType", 3727db96d56Sopenharmony_ci .tp_basicsize = sizeof(PyWeakReference), 3737db96d56Sopenharmony_ci .tp_dealloc = weakref_dealloc, 3747db96d56Sopenharmony_ci .tp_vectorcall_offset = offsetof(PyWeakReference, vectorcall), 3757db96d56Sopenharmony_ci .tp_call = PyVectorcall_Call, 3767db96d56Sopenharmony_ci .tp_repr = (reprfunc)weakref_repr, 3777db96d56Sopenharmony_ci .tp_hash = (hashfunc)weakref_hash, 3787db96d56Sopenharmony_ci .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 3797db96d56Sopenharmony_ci Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_BASETYPE, 3807db96d56Sopenharmony_ci .tp_traverse = (traverseproc)gc_traverse, 3817db96d56Sopenharmony_ci .tp_clear = (inquiry)gc_clear, 3827db96d56Sopenharmony_ci .tp_richcompare = (richcmpfunc)weakref_richcompare, 3837db96d56Sopenharmony_ci .tp_methods = weakref_methods, 3847db96d56Sopenharmony_ci .tp_members = weakref_members, 3857db96d56Sopenharmony_ci .tp_init = weakref___init__, 3867db96d56Sopenharmony_ci .tp_alloc = PyType_GenericAlloc, 3877db96d56Sopenharmony_ci .tp_new = weakref___new__, 3887db96d56Sopenharmony_ci .tp_free = PyObject_GC_Del, 3897db96d56Sopenharmony_ci}; 3907db96d56Sopenharmony_ci 3917db96d56Sopenharmony_ci 3927db96d56Sopenharmony_cistatic int 3937db96d56Sopenharmony_ciproxy_checkref(PyWeakReference *proxy) 3947db96d56Sopenharmony_ci{ 3957db96d56Sopenharmony_ci if (PyWeakref_GET_OBJECT(proxy) == Py_None) { 3967db96d56Sopenharmony_ci PyErr_SetString(PyExc_ReferenceError, 3977db96d56Sopenharmony_ci "weakly-referenced object no longer exists"); 3987db96d56Sopenharmony_ci return 0; 3997db96d56Sopenharmony_ci } 4007db96d56Sopenharmony_ci return 1; 4017db96d56Sopenharmony_ci} 4027db96d56Sopenharmony_ci 4037db96d56Sopenharmony_ci 4047db96d56Sopenharmony_ci/* If a parameter is a proxy, check that it is still "live" and wrap it, 4057db96d56Sopenharmony_ci * replacing the original value with the raw object. Raises ReferenceError 4067db96d56Sopenharmony_ci * if the param is a dead proxy. 4077db96d56Sopenharmony_ci */ 4087db96d56Sopenharmony_ci#define UNWRAP(o) \ 4097db96d56Sopenharmony_ci if (PyWeakref_CheckProxy(o)) { \ 4107db96d56Sopenharmony_ci if (!proxy_checkref((PyWeakReference *)o)) \ 4117db96d56Sopenharmony_ci return NULL; \ 4127db96d56Sopenharmony_ci o = PyWeakref_GET_OBJECT(o); \ 4137db96d56Sopenharmony_ci } 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ci#define WRAP_UNARY(method, generic) \ 4167db96d56Sopenharmony_ci static PyObject * \ 4177db96d56Sopenharmony_ci method(PyObject *proxy) { \ 4187db96d56Sopenharmony_ci UNWRAP(proxy); \ 4197db96d56Sopenharmony_ci Py_INCREF(proxy); \ 4207db96d56Sopenharmony_ci PyObject* res = generic(proxy); \ 4217db96d56Sopenharmony_ci Py_DECREF(proxy); \ 4227db96d56Sopenharmony_ci return res; \ 4237db96d56Sopenharmony_ci } 4247db96d56Sopenharmony_ci 4257db96d56Sopenharmony_ci#define WRAP_BINARY(method, generic) \ 4267db96d56Sopenharmony_ci static PyObject * \ 4277db96d56Sopenharmony_ci method(PyObject *x, PyObject *y) { \ 4287db96d56Sopenharmony_ci UNWRAP(x); \ 4297db96d56Sopenharmony_ci UNWRAP(y); \ 4307db96d56Sopenharmony_ci Py_INCREF(x); \ 4317db96d56Sopenharmony_ci Py_INCREF(y); \ 4327db96d56Sopenharmony_ci PyObject* res = generic(x, y); \ 4337db96d56Sopenharmony_ci Py_DECREF(x); \ 4347db96d56Sopenharmony_ci Py_DECREF(y); \ 4357db96d56Sopenharmony_ci return res; \ 4367db96d56Sopenharmony_ci } 4377db96d56Sopenharmony_ci 4387db96d56Sopenharmony_ci/* Note that the third arg needs to be checked for NULL since the tp_call 4397db96d56Sopenharmony_ci * slot can receive NULL for this arg. 4407db96d56Sopenharmony_ci */ 4417db96d56Sopenharmony_ci#define WRAP_TERNARY(method, generic) \ 4427db96d56Sopenharmony_ci static PyObject * \ 4437db96d56Sopenharmony_ci method(PyObject *proxy, PyObject *v, PyObject *w) { \ 4447db96d56Sopenharmony_ci UNWRAP(proxy); \ 4457db96d56Sopenharmony_ci UNWRAP(v); \ 4467db96d56Sopenharmony_ci if (w != NULL) \ 4477db96d56Sopenharmony_ci UNWRAP(w); \ 4487db96d56Sopenharmony_ci Py_INCREF(proxy); \ 4497db96d56Sopenharmony_ci Py_INCREF(v); \ 4507db96d56Sopenharmony_ci Py_XINCREF(w); \ 4517db96d56Sopenharmony_ci PyObject* res = generic(proxy, v, w); \ 4527db96d56Sopenharmony_ci Py_DECREF(proxy); \ 4537db96d56Sopenharmony_ci Py_DECREF(v); \ 4547db96d56Sopenharmony_ci Py_XDECREF(w); \ 4557db96d56Sopenharmony_ci return res; \ 4567db96d56Sopenharmony_ci } 4577db96d56Sopenharmony_ci 4587db96d56Sopenharmony_ci#define WRAP_METHOD(method, SPECIAL) \ 4597db96d56Sopenharmony_ci static PyObject * \ 4607db96d56Sopenharmony_ci method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \ 4617db96d56Sopenharmony_ci UNWRAP(proxy); \ 4627db96d56Sopenharmony_ci Py_INCREF(proxy); \ 4637db96d56Sopenharmony_ci PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \ 4647db96d56Sopenharmony_ci Py_DECREF(proxy); \ 4657db96d56Sopenharmony_ci return res; \ 4667db96d56Sopenharmony_ci } 4677db96d56Sopenharmony_ci 4687db96d56Sopenharmony_ci 4697db96d56Sopenharmony_ci/* direct slots */ 4707db96d56Sopenharmony_ci 4717db96d56Sopenharmony_ciWRAP_BINARY(proxy_getattr, PyObject_GetAttr) 4727db96d56Sopenharmony_ciWRAP_UNARY(proxy_str, PyObject_Str) 4737db96d56Sopenharmony_ciWRAP_TERNARY(proxy_call, PyObject_Call) 4747db96d56Sopenharmony_ci 4757db96d56Sopenharmony_cistatic PyObject * 4767db96d56Sopenharmony_ciproxy_repr(PyWeakReference *proxy) 4777db96d56Sopenharmony_ci{ 4787db96d56Sopenharmony_ci return PyUnicode_FromFormat( 4797db96d56Sopenharmony_ci "<weakproxy at %p to %s at %p>", 4807db96d56Sopenharmony_ci proxy, 4817db96d56Sopenharmony_ci Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name, 4827db96d56Sopenharmony_ci PyWeakref_GET_OBJECT(proxy)); 4837db96d56Sopenharmony_ci} 4847db96d56Sopenharmony_ci 4857db96d56Sopenharmony_ci 4867db96d56Sopenharmony_cistatic int 4877db96d56Sopenharmony_ciproxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value) 4887db96d56Sopenharmony_ci{ 4897db96d56Sopenharmony_ci if (!proxy_checkref(proxy)) 4907db96d56Sopenharmony_ci return -1; 4917db96d56Sopenharmony_ci PyObject *obj = PyWeakref_GET_OBJECT(proxy); 4927db96d56Sopenharmony_ci Py_INCREF(obj); 4937db96d56Sopenharmony_ci int res = PyObject_SetAttr(obj, name, value); 4947db96d56Sopenharmony_ci Py_DECREF(obj); 4957db96d56Sopenharmony_ci return res; 4967db96d56Sopenharmony_ci} 4977db96d56Sopenharmony_ci 4987db96d56Sopenharmony_cistatic PyObject * 4997db96d56Sopenharmony_ciproxy_richcompare(PyObject *proxy, PyObject *v, int op) 5007db96d56Sopenharmony_ci{ 5017db96d56Sopenharmony_ci UNWRAP(proxy); 5027db96d56Sopenharmony_ci UNWRAP(v); 5037db96d56Sopenharmony_ci return PyObject_RichCompare(proxy, v, op); 5047db96d56Sopenharmony_ci} 5057db96d56Sopenharmony_ci 5067db96d56Sopenharmony_ci/* number slots */ 5077db96d56Sopenharmony_ciWRAP_BINARY(proxy_add, PyNumber_Add) 5087db96d56Sopenharmony_ciWRAP_BINARY(proxy_sub, PyNumber_Subtract) 5097db96d56Sopenharmony_ciWRAP_BINARY(proxy_mul, PyNumber_Multiply) 5107db96d56Sopenharmony_ciWRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide) 5117db96d56Sopenharmony_ciWRAP_BINARY(proxy_true_div, PyNumber_TrueDivide) 5127db96d56Sopenharmony_ciWRAP_BINARY(proxy_mod, PyNumber_Remainder) 5137db96d56Sopenharmony_ciWRAP_BINARY(proxy_divmod, PyNumber_Divmod) 5147db96d56Sopenharmony_ciWRAP_TERNARY(proxy_pow, PyNumber_Power) 5157db96d56Sopenharmony_ciWRAP_UNARY(proxy_neg, PyNumber_Negative) 5167db96d56Sopenharmony_ciWRAP_UNARY(proxy_pos, PyNumber_Positive) 5177db96d56Sopenharmony_ciWRAP_UNARY(proxy_abs, PyNumber_Absolute) 5187db96d56Sopenharmony_ciWRAP_UNARY(proxy_invert, PyNumber_Invert) 5197db96d56Sopenharmony_ciWRAP_BINARY(proxy_lshift, PyNumber_Lshift) 5207db96d56Sopenharmony_ciWRAP_BINARY(proxy_rshift, PyNumber_Rshift) 5217db96d56Sopenharmony_ciWRAP_BINARY(proxy_and, PyNumber_And) 5227db96d56Sopenharmony_ciWRAP_BINARY(proxy_xor, PyNumber_Xor) 5237db96d56Sopenharmony_ciWRAP_BINARY(proxy_or, PyNumber_Or) 5247db96d56Sopenharmony_ciWRAP_UNARY(proxy_int, PyNumber_Long) 5257db96d56Sopenharmony_ciWRAP_UNARY(proxy_float, PyNumber_Float) 5267db96d56Sopenharmony_ciWRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd) 5277db96d56Sopenharmony_ciWRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract) 5287db96d56Sopenharmony_ciWRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply) 5297db96d56Sopenharmony_ciWRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide) 5307db96d56Sopenharmony_ciWRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide) 5317db96d56Sopenharmony_ciWRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder) 5327db96d56Sopenharmony_ciWRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower) 5337db96d56Sopenharmony_ciWRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift) 5347db96d56Sopenharmony_ciWRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift) 5357db96d56Sopenharmony_ciWRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd) 5367db96d56Sopenharmony_ciWRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor) 5377db96d56Sopenharmony_ciWRAP_BINARY(proxy_ior, PyNumber_InPlaceOr) 5387db96d56Sopenharmony_ciWRAP_UNARY(proxy_index, PyNumber_Index) 5397db96d56Sopenharmony_ciWRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply) 5407db96d56Sopenharmony_ciWRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply) 5417db96d56Sopenharmony_ci 5427db96d56Sopenharmony_cistatic int 5437db96d56Sopenharmony_ciproxy_bool(PyWeakReference *proxy) 5447db96d56Sopenharmony_ci{ 5457db96d56Sopenharmony_ci PyObject *o = PyWeakref_GET_OBJECT(proxy); 5467db96d56Sopenharmony_ci if (!proxy_checkref(proxy)) { 5477db96d56Sopenharmony_ci return -1; 5487db96d56Sopenharmony_ci } 5497db96d56Sopenharmony_ci Py_INCREF(o); 5507db96d56Sopenharmony_ci int res = PyObject_IsTrue(o); 5517db96d56Sopenharmony_ci Py_DECREF(o); 5527db96d56Sopenharmony_ci return res; 5537db96d56Sopenharmony_ci} 5547db96d56Sopenharmony_ci 5557db96d56Sopenharmony_cistatic void 5567db96d56Sopenharmony_ciproxy_dealloc(PyWeakReference *self) 5577db96d56Sopenharmony_ci{ 5587db96d56Sopenharmony_ci PyObject_GC_UnTrack(self); 5597db96d56Sopenharmony_ci if (self->wr_callback != NULL) 5607db96d56Sopenharmony_ci PyObject_GC_UnTrack((PyObject *)self); 5617db96d56Sopenharmony_ci clear_weakref(self); 5627db96d56Sopenharmony_ci PyObject_GC_Del(self); 5637db96d56Sopenharmony_ci} 5647db96d56Sopenharmony_ci 5657db96d56Sopenharmony_ci/* sequence slots */ 5667db96d56Sopenharmony_ci 5677db96d56Sopenharmony_cistatic int 5687db96d56Sopenharmony_ciproxy_contains(PyWeakReference *proxy, PyObject *value) 5697db96d56Sopenharmony_ci{ 5707db96d56Sopenharmony_ci if (!proxy_checkref(proxy)) 5717db96d56Sopenharmony_ci return -1; 5727db96d56Sopenharmony_ci 5737db96d56Sopenharmony_ci PyObject *obj = PyWeakref_GET_OBJECT(proxy); 5747db96d56Sopenharmony_ci Py_INCREF(obj); 5757db96d56Sopenharmony_ci int res = PySequence_Contains(obj, value); 5767db96d56Sopenharmony_ci Py_DECREF(obj); 5777db96d56Sopenharmony_ci return res; 5787db96d56Sopenharmony_ci} 5797db96d56Sopenharmony_ci 5807db96d56Sopenharmony_ci/* mapping slots */ 5817db96d56Sopenharmony_ci 5827db96d56Sopenharmony_cistatic Py_ssize_t 5837db96d56Sopenharmony_ciproxy_length(PyWeakReference *proxy) 5847db96d56Sopenharmony_ci{ 5857db96d56Sopenharmony_ci if (!proxy_checkref(proxy)) 5867db96d56Sopenharmony_ci return -1; 5877db96d56Sopenharmony_ci 5887db96d56Sopenharmony_ci PyObject *obj = PyWeakref_GET_OBJECT(proxy); 5897db96d56Sopenharmony_ci Py_INCREF(obj); 5907db96d56Sopenharmony_ci Py_ssize_t res = PyObject_Length(obj); 5917db96d56Sopenharmony_ci Py_DECREF(obj); 5927db96d56Sopenharmony_ci return res; 5937db96d56Sopenharmony_ci} 5947db96d56Sopenharmony_ci 5957db96d56Sopenharmony_ciWRAP_BINARY(proxy_getitem, PyObject_GetItem) 5967db96d56Sopenharmony_ci 5977db96d56Sopenharmony_cistatic int 5987db96d56Sopenharmony_ciproxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value) 5997db96d56Sopenharmony_ci{ 6007db96d56Sopenharmony_ci if (!proxy_checkref(proxy)) 6017db96d56Sopenharmony_ci return -1; 6027db96d56Sopenharmony_ci 6037db96d56Sopenharmony_ci PyObject *obj = PyWeakref_GET_OBJECT(proxy); 6047db96d56Sopenharmony_ci Py_INCREF(obj); 6057db96d56Sopenharmony_ci int res; 6067db96d56Sopenharmony_ci if (value == NULL) { 6077db96d56Sopenharmony_ci res = PyObject_DelItem(obj, key); 6087db96d56Sopenharmony_ci } else { 6097db96d56Sopenharmony_ci res = PyObject_SetItem(obj, key, value); 6107db96d56Sopenharmony_ci } 6117db96d56Sopenharmony_ci Py_DECREF(obj); 6127db96d56Sopenharmony_ci return res; 6137db96d56Sopenharmony_ci} 6147db96d56Sopenharmony_ci 6157db96d56Sopenharmony_ci/* iterator slots */ 6167db96d56Sopenharmony_ci 6177db96d56Sopenharmony_cistatic PyObject * 6187db96d56Sopenharmony_ciproxy_iter(PyWeakReference *proxy) 6197db96d56Sopenharmony_ci{ 6207db96d56Sopenharmony_ci if (!proxy_checkref(proxy)) 6217db96d56Sopenharmony_ci return NULL; 6227db96d56Sopenharmony_ci PyObject *obj = PyWeakref_GET_OBJECT(proxy); 6237db96d56Sopenharmony_ci Py_INCREF(obj); 6247db96d56Sopenharmony_ci PyObject* res = PyObject_GetIter(obj); 6257db96d56Sopenharmony_ci Py_DECREF(obj); 6267db96d56Sopenharmony_ci return res; 6277db96d56Sopenharmony_ci} 6287db96d56Sopenharmony_ci 6297db96d56Sopenharmony_cistatic PyObject * 6307db96d56Sopenharmony_ciproxy_iternext(PyWeakReference *proxy) 6317db96d56Sopenharmony_ci{ 6327db96d56Sopenharmony_ci if (!proxy_checkref(proxy)) 6337db96d56Sopenharmony_ci return NULL; 6347db96d56Sopenharmony_ci 6357db96d56Sopenharmony_ci PyObject *obj = PyWeakref_GET_OBJECT(proxy); 6367db96d56Sopenharmony_ci if (!PyIter_Check(obj)) { 6377db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 6387db96d56Sopenharmony_ci "Weakref proxy referenced a non-iterator '%.200s' object", 6397db96d56Sopenharmony_ci Py_TYPE(obj)->tp_name); 6407db96d56Sopenharmony_ci return NULL; 6417db96d56Sopenharmony_ci } 6427db96d56Sopenharmony_ci Py_INCREF(obj); 6437db96d56Sopenharmony_ci PyObject* res = PyIter_Next(obj); 6447db96d56Sopenharmony_ci Py_DECREF(obj); 6457db96d56Sopenharmony_ci return res; 6467db96d56Sopenharmony_ci} 6477db96d56Sopenharmony_ci 6487db96d56Sopenharmony_ci 6497db96d56Sopenharmony_ciWRAP_METHOD(proxy_bytes, __bytes__) 6507db96d56Sopenharmony_ciWRAP_METHOD(proxy_reversed, __reversed__) 6517db96d56Sopenharmony_ci 6527db96d56Sopenharmony_ci 6537db96d56Sopenharmony_cistatic PyMethodDef proxy_methods[] = { 6547db96d56Sopenharmony_ci {"__bytes__", proxy_bytes, METH_NOARGS}, 6557db96d56Sopenharmony_ci {"__reversed__", proxy_reversed, METH_NOARGS}, 6567db96d56Sopenharmony_ci {NULL, NULL} 6577db96d56Sopenharmony_ci}; 6587db96d56Sopenharmony_ci 6597db96d56Sopenharmony_ci 6607db96d56Sopenharmony_cistatic PyNumberMethods proxy_as_number = { 6617db96d56Sopenharmony_ci proxy_add, /*nb_add*/ 6627db96d56Sopenharmony_ci proxy_sub, /*nb_subtract*/ 6637db96d56Sopenharmony_ci proxy_mul, /*nb_multiply*/ 6647db96d56Sopenharmony_ci proxy_mod, /*nb_remainder*/ 6657db96d56Sopenharmony_ci proxy_divmod, /*nb_divmod*/ 6667db96d56Sopenharmony_ci proxy_pow, /*nb_power*/ 6677db96d56Sopenharmony_ci proxy_neg, /*nb_negative*/ 6687db96d56Sopenharmony_ci proxy_pos, /*nb_positive*/ 6697db96d56Sopenharmony_ci proxy_abs, /*nb_absolute*/ 6707db96d56Sopenharmony_ci (inquiry)proxy_bool, /*nb_bool*/ 6717db96d56Sopenharmony_ci proxy_invert, /*nb_invert*/ 6727db96d56Sopenharmony_ci proxy_lshift, /*nb_lshift*/ 6737db96d56Sopenharmony_ci proxy_rshift, /*nb_rshift*/ 6747db96d56Sopenharmony_ci proxy_and, /*nb_and*/ 6757db96d56Sopenharmony_ci proxy_xor, /*nb_xor*/ 6767db96d56Sopenharmony_ci proxy_or, /*nb_or*/ 6777db96d56Sopenharmony_ci proxy_int, /*nb_int*/ 6787db96d56Sopenharmony_ci 0, /*nb_reserved*/ 6797db96d56Sopenharmony_ci proxy_float, /*nb_float*/ 6807db96d56Sopenharmony_ci proxy_iadd, /*nb_inplace_add*/ 6817db96d56Sopenharmony_ci proxy_isub, /*nb_inplace_subtract*/ 6827db96d56Sopenharmony_ci proxy_imul, /*nb_inplace_multiply*/ 6837db96d56Sopenharmony_ci proxy_imod, /*nb_inplace_remainder*/ 6847db96d56Sopenharmony_ci proxy_ipow, /*nb_inplace_power*/ 6857db96d56Sopenharmony_ci proxy_ilshift, /*nb_inplace_lshift*/ 6867db96d56Sopenharmony_ci proxy_irshift, /*nb_inplace_rshift*/ 6877db96d56Sopenharmony_ci proxy_iand, /*nb_inplace_and*/ 6887db96d56Sopenharmony_ci proxy_ixor, /*nb_inplace_xor*/ 6897db96d56Sopenharmony_ci proxy_ior, /*nb_inplace_or*/ 6907db96d56Sopenharmony_ci proxy_floor_div, /*nb_floor_divide*/ 6917db96d56Sopenharmony_ci proxy_true_div, /*nb_true_divide*/ 6927db96d56Sopenharmony_ci proxy_ifloor_div, /*nb_inplace_floor_divide*/ 6937db96d56Sopenharmony_ci proxy_itrue_div, /*nb_inplace_true_divide*/ 6947db96d56Sopenharmony_ci proxy_index, /*nb_index*/ 6957db96d56Sopenharmony_ci proxy_matmul, /*nb_matrix_multiply*/ 6967db96d56Sopenharmony_ci proxy_imatmul, /*nb_inplace_matrix_multiply*/ 6977db96d56Sopenharmony_ci}; 6987db96d56Sopenharmony_ci 6997db96d56Sopenharmony_cistatic PySequenceMethods proxy_as_sequence = { 7007db96d56Sopenharmony_ci (lenfunc)proxy_length, /*sq_length*/ 7017db96d56Sopenharmony_ci 0, /*sq_concat*/ 7027db96d56Sopenharmony_ci 0, /*sq_repeat*/ 7037db96d56Sopenharmony_ci 0, /*sq_item*/ 7047db96d56Sopenharmony_ci 0, /*sq_slice*/ 7057db96d56Sopenharmony_ci 0, /*sq_ass_item*/ 7067db96d56Sopenharmony_ci 0, /*sq_ass_slice*/ 7077db96d56Sopenharmony_ci (objobjproc)proxy_contains, /* sq_contains */ 7087db96d56Sopenharmony_ci}; 7097db96d56Sopenharmony_ci 7107db96d56Sopenharmony_cistatic PyMappingMethods proxy_as_mapping = { 7117db96d56Sopenharmony_ci (lenfunc)proxy_length, /*mp_length*/ 7127db96d56Sopenharmony_ci proxy_getitem, /*mp_subscript*/ 7137db96d56Sopenharmony_ci (objobjargproc)proxy_setitem, /*mp_ass_subscript*/ 7147db96d56Sopenharmony_ci}; 7157db96d56Sopenharmony_ci 7167db96d56Sopenharmony_ci 7177db96d56Sopenharmony_ciPyTypeObject 7187db96d56Sopenharmony_ci_PyWeakref_ProxyType = { 7197db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(&PyType_Type, 0) 7207db96d56Sopenharmony_ci "weakref.ProxyType", 7217db96d56Sopenharmony_ci sizeof(PyWeakReference), 7227db96d56Sopenharmony_ci 0, 7237db96d56Sopenharmony_ci /* methods */ 7247db96d56Sopenharmony_ci (destructor)proxy_dealloc, /* tp_dealloc */ 7257db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 7267db96d56Sopenharmony_ci 0, /* tp_getattr */ 7277db96d56Sopenharmony_ci 0, /* tp_setattr */ 7287db96d56Sopenharmony_ci 0, /* tp_as_async */ 7297db96d56Sopenharmony_ci (reprfunc)proxy_repr, /* tp_repr */ 7307db96d56Sopenharmony_ci &proxy_as_number, /* tp_as_number */ 7317db96d56Sopenharmony_ci &proxy_as_sequence, /* tp_as_sequence */ 7327db96d56Sopenharmony_ci &proxy_as_mapping, /* tp_as_mapping */ 7337db96d56Sopenharmony_ci// Notice that tp_hash is intentionally omitted as proxies are "mutable" (when the reference dies). 7347db96d56Sopenharmony_ci 0, /* tp_hash */ 7357db96d56Sopenharmony_ci 0, /* tp_call */ 7367db96d56Sopenharmony_ci proxy_str, /* tp_str */ 7377db96d56Sopenharmony_ci proxy_getattr, /* tp_getattro */ 7387db96d56Sopenharmony_ci (setattrofunc)proxy_setattr, /* tp_setattro */ 7397db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 7407db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 7417db96d56Sopenharmony_ci 0, /* tp_doc */ 7427db96d56Sopenharmony_ci (traverseproc)gc_traverse, /* tp_traverse */ 7437db96d56Sopenharmony_ci (inquiry)gc_clear, /* tp_clear */ 7447db96d56Sopenharmony_ci proxy_richcompare, /* tp_richcompare */ 7457db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 7467db96d56Sopenharmony_ci (getiterfunc)proxy_iter, /* tp_iter */ 7477db96d56Sopenharmony_ci (iternextfunc)proxy_iternext, /* tp_iternext */ 7487db96d56Sopenharmony_ci proxy_methods, /* tp_methods */ 7497db96d56Sopenharmony_ci}; 7507db96d56Sopenharmony_ci 7517db96d56Sopenharmony_ci 7527db96d56Sopenharmony_ciPyTypeObject 7537db96d56Sopenharmony_ci_PyWeakref_CallableProxyType = { 7547db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(&PyType_Type, 0) 7557db96d56Sopenharmony_ci "weakref.CallableProxyType", 7567db96d56Sopenharmony_ci sizeof(PyWeakReference), 7577db96d56Sopenharmony_ci 0, 7587db96d56Sopenharmony_ci /* methods */ 7597db96d56Sopenharmony_ci (destructor)proxy_dealloc, /* tp_dealloc */ 7607db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 7617db96d56Sopenharmony_ci 0, /* tp_getattr */ 7627db96d56Sopenharmony_ci 0, /* tp_setattr */ 7637db96d56Sopenharmony_ci 0, /* tp_as_async */ 7647db96d56Sopenharmony_ci (unaryfunc)proxy_repr, /* tp_repr */ 7657db96d56Sopenharmony_ci &proxy_as_number, /* tp_as_number */ 7667db96d56Sopenharmony_ci &proxy_as_sequence, /* tp_as_sequence */ 7677db96d56Sopenharmony_ci &proxy_as_mapping, /* tp_as_mapping */ 7687db96d56Sopenharmony_ci 0, /* tp_hash */ 7697db96d56Sopenharmony_ci proxy_call, /* tp_call */ 7707db96d56Sopenharmony_ci proxy_str, /* tp_str */ 7717db96d56Sopenharmony_ci proxy_getattr, /* tp_getattro */ 7727db96d56Sopenharmony_ci (setattrofunc)proxy_setattr, /* tp_setattro */ 7737db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 7747db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 7757db96d56Sopenharmony_ci 0, /* tp_doc */ 7767db96d56Sopenharmony_ci (traverseproc)gc_traverse, /* tp_traverse */ 7777db96d56Sopenharmony_ci (inquiry)gc_clear, /* tp_clear */ 7787db96d56Sopenharmony_ci proxy_richcompare, /* tp_richcompare */ 7797db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 7807db96d56Sopenharmony_ci (getiterfunc)proxy_iter, /* tp_iter */ 7817db96d56Sopenharmony_ci (iternextfunc)proxy_iternext, /* tp_iternext */ 7827db96d56Sopenharmony_ci}; 7837db96d56Sopenharmony_ci 7847db96d56Sopenharmony_ci 7857db96d56Sopenharmony_ci 7867db96d56Sopenharmony_ciPyObject * 7877db96d56Sopenharmony_ciPyWeakref_NewRef(PyObject *ob, PyObject *callback) 7887db96d56Sopenharmony_ci{ 7897db96d56Sopenharmony_ci PyWeakReference *result = NULL; 7907db96d56Sopenharmony_ci PyWeakReference **list; 7917db96d56Sopenharmony_ci PyWeakReference *ref, *proxy; 7927db96d56Sopenharmony_ci 7937db96d56Sopenharmony_ci if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { 7947db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 7957db96d56Sopenharmony_ci "cannot create weak reference to '%s' object", 7967db96d56Sopenharmony_ci Py_TYPE(ob)->tp_name); 7977db96d56Sopenharmony_ci return NULL; 7987db96d56Sopenharmony_ci } 7997db96d56Sopenharmony_ci list = GET_WEAKREFS_LISTPTR(ob); 8007db96d56Sopenharmony_ci get_basic_refs(*list, &ref, &proxy); 8017db96d56Sopenharmony_ci if (callback == Py_None) 8027db96d56Sopenharmony_ci callback = NULL; 8037db96d56Sopenharmony_ci if (callback == NULL) 8047db96d56Sopenharmony_ci /* return existing weak reference if it exists */ 8057db96d56Sopenharmony_ci result = ref; 8067db96d56Sopenharmony_ci if (result != NULL) 8077db96d56Sopenharmony_ci Py_INCREF(result); 8087db96d56Sopenharmony_ci else { 8097db96d56Sopenharmony_ci /* Note: new_weakref() can trigger cyclic GC, so the weakref 8107db96d56Sopenharmony_ci list on ob can be mutated. This means that the ref and 8117db96d56Sopenharmony_ci proxy pointers we got back earlier may have been collected, 8127db96d56Sopenharmony_ci so we need to compute these values again before we use 8137db96d56Sopenharmony_ci them. */ 8147db96d56Sopenharmony_ci result = new_weakref(ob, callback); 8157db96d56Sopenharmony_ci if (result != NULL) { 8167db96d56Sopenharmony_ci get_basic_refs(*list, &ref, &proxy); 8177db96d56Sopenharmony_ci if (callback == NULL) { 8187db96d56Sopenharmony_ci if (ref == NULL) 8197db96d56Sopenharmony_ci insert_head(result, list); 8207db96d56Sopenharmony_ci else { 8217db96d56Sopenharmony_ci /* Someone else added a ref without a callback 8227db96d56Sopenharmony_ci during GC. Return that one instead of this one 8237db96d56Sopenharmony_ci to avoid violating the invariants of the list 8247db96d56Sopenharmony_ci of weakrefs for ob. */ 8257db96d56Sopenharmony_ci Py_DECREF(result); 8267db96d56Sopenharmony_ci Py_INCREF(ref); 8277db96d56Sopenharmony_ci result = ref; 8287db96d56Sopenharmony_ci } 8297db96d56Sopenharmony_ci } 8307db96d56Sopenharmony_ci else { 8317db96d56Sopenharmony_ci PyWeakReference *prev; 8327db96d56Sopenharmony_ci 8337db96d56Sopenharmony_ci prev = (proxy == NULL) ? ref : proxy; 8347db96d56Sopenharmony_ci if (prev == NULL) 8357db96d56Sopenharmony_ci insert_head(result, list); 8367db96d56Sopenharmony_ci else 8377db96d56Sopenharmony_ci insert_after(result, prev); 8387db96d56Sopenharmony_ci } 8397db96d56Sopenharmony_ci } 8407db96d56Sopenharmony_ci } 8417db96d56Sopenharmony_ci return (PyObject *) result; 8427db96d56Sopenharmony_ci} 8437db96d56Sopenharmony_ci 8447db96d56Sopenharmony_ci 8457db96d56Sopenharmony_ciPyObject * 8467db96d56Sopenharmony_ciPyWeakref_NewProxy(PyObject *ob, PyObject *callback) 8477db96d56Sopenharmony_ci{ 8487db96d56Sopenharmony_ci PyWeakReference *result = NULL; 8497db96d56Sopenharmony_ci PyWeakReference **list; 8507db96d56Sopenharmony_ci PyWeakReference *ref, *proxy; 8517db96d56Sopenharmony_ci 8527db96d56Sopenharmony_ci if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { 8537db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 8547db96d56Sopenharmony_ci "cannot create weak reference to '%s' object", 8557db96d56Sopenharmony_ci Py_TYPE(ob)->tp_name); 8567db96d56Sopenharmony_ci return NULL; 8577db96d56Sopenharmony_ci } 8587db96d56Sopenharmony_ci list = GET_WEAKREFS_LISTPTR(ob); 8597db96d56Sopenharmony_ci get_basic_refs(*list, &ref, &proxy); 8607db96d56Sopenharmony_ci if (callback == Py_None) 8617db96d56Sopenharmony_ci callback = NULL; 8627db96d56Sopenharmony_ci if (callback == NULL) 8637db96d56Sopenharmony_ci /* attempt to return an existing weak reference if it exists */ 8647db96d56Sopenharmony_ci result = proxy; 8657db96d56Sopenharmony_ci if (result != NULL) 8667db96d56Sopenharmony_ci Py_INCREF(result); 8677db96d56Sopenharmony_ci else { 8687db96d56Sopenharmony_ci /* Note: new_weakref() can trigger cyclic GC, so the weakref 8697db96d56Sopenharmony_ci list on ob can be mutated. This means that the ref and 8707db96d56Sopenharmony_ci proxy pointers we got back earlier may have been collected, 8717db96d56Sopenharmony_ci so we need to compute these values again before we use 8727db96d56Sopenharmony_ci them. */ 8737db96d56Sopenharmony_ci result = new_weakref(ob, callback); 8747db96d56Sopenharmony_ci if (result != NULL) { 8757db96d56Sopenharmony_ci PyWeakReference *prev; 8767db96d56Sopenharmony_ci 8777db96d56Sopenharmony_ci if (PyCallable_Check(ob)) { 8787db96d56Sopenharmony_ci Py_SET_TYPE(result, &_PyWeakref_CallableProxyType); 8797db96d56Sopenharmony_ci } 8807db96d56Sopenharmony_ci else { 8817db96d56Sopenharmony_ci Py_SET_TYPE(result, &_PyWeakref_ProxyType); 8827db96d56Sopenharmony_ci } 8837db96d56Sopenharmony_ci get_basic_refs(*list, &ref, &proxy); 8847db96d56Sopenharmony_ci if (callback == NULL) { 8857db96d56Sopenharmony_ci if (proxy != NULL) { 8867db96d56Sopenharmony_ci /* Someone else added a proxy without a callback 8877db96d56Sopenharmony_ci during GC. Return that one instead of this one 8887db96d56Sopenharmony_ci to avoid violating the invariants of the list 8897db96d56Sopenharmony_ci of weakrefs for ob. */ 8907db96d56Sopenharmony_ci Py_DECREF(result); 8917db96d56Sopenharmony_ci result = proxy; 8927db96d56Sopenharmony_ci Py_INCREF(result); 8937db96d56Sopenharmony_ci goto skip_insert; 8947db96d56Sopenharmony_ci } 8957db96d56Sopenharmony_ci prev = ref; 8967db96d56Sopenharmony_ci } 8977db96d56Sopenharmony_ci else 8987db96d56Sopenharmony_ci prev = (proxy == NULL) ? ref : proxy; 8997db96d56Sopenharmony_ci 9007db96d56Sopenharmony_ci if (prev == NULL) 9017db96d56Sopenharmony_ci insert_head(result, list); 9027db96d56Sopenharmony_ci else 9037db96d56Sopenharmony_ci insert_after(result, prev); 9047db96d56Sopenharmony_ci skip_insert: 9057db96d56Sopenharmony_ci ; 9067db96d56Sopenharmony_ci } 9077db96d56Sopenharmony_ci } 9087db96d56Sopenharmony_ci return (PyObject *) result; 9097db96d56Sopenharmony_ci} 9107db96d56Sopenharmony_ci 9117db96d56Sopenharmony_ci 9127db96d56Sopenharmony_ciPyObject * 9137db96d56Sopenharmony_ciPyWeakref_GetObject(PyObject *ref) 9147db96d56Sopenharmony_ci{ 9157db96d56Sopenharmony_ci if (ref == NULL || !PyWeakref_Check(ref)) { 9167db96d56Sopenharmony_ci PyErr_BadInternalCall(); 9177db96d56Sopenharmony_ci return NULL; 9187db96d56Sopenharmony_ci } 9197db96d56Sopenharmony_ci return PyWeakref_GET_OBJECT(ref); 9207db96d56Sopenharmony_ci} 9217db96d56Sopenharmony_ci 9227db96d56Sopenharmony_ci/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's 9237db96d56Sopenharmony_ci * handle_weakrefs(). 9247db96d56Sopenharmony_ci */ 9257db96d56Sopenharmony_cistatic void 9267db96d56Sopenharmony_cihandle_callback(PyWeakReference *ref, PyObject *callback) 9277db96d56Sopenharmony_ci{ 9287db96d56Sopenharmony_ci PyObject *cbresult = PyObject_CallOneArg(callback, (PyObject *)ref); 9297db96d56Sopenharmony_ci 9307db96d56Sopenharmony_ci if (cbresult == NULL) 9317db96d56Sopenharmony_ci PyErr_WriteUnraisable(callback); 9327db96d56Sopenharmony_ci else 9337db96d56Sopenharmony_ci Py_DECREF(cbresult); 9347db96d56Sopenharmony_ci} 9357db96d56Sopenharmony_ci 9367db96d56Sopenharmony_ci/* This function is called by the tp_dealloc handler to clear weak references. 9377db96d56Sopenharmony_ci * 9387db96d56Sopenharmony_ci * This iterates through the weak references for 'object' and calls callbacks 9397db96d56Sopenharmony_ci * for those references which have one. It returns when all callbacks have 9407db96d56Sopenharmony_ci * been attempted. 9417db96d56Sopenharmony_ci */ 9427db96d56Sopenharmony_civoid 9437db96d56Sopenharmony_ciPyObject_ClearWeakRefs(PyObject *object) 9447db96d56Sopenharmony_ci{ 9457db96d56Sopenharmony_ci PyWeakReference **list; 9467db96d56Sopenharmony_ci 9477db96d56Sopenharmony_ci if (object == NULL 9487db96d56Sopenharmony_ci || !_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object)) 9497db96d56Sopenharmony_ci || Py_REFCNT(object) != 0) 9507db96d56Sopenharmony_ci { 9517db96d56Sopenharmony_ci PyErr_BadInternalCall(); 9527db96d56Sopenharmony_ci return; 9537db96d56Sopenharmony_ci } 9547db96d56Sopenharmony_ci list = GET_WEAKREFS_LISTPTR(object); 9557db96d56Sopenharmony_ci /* Remove the callback-less basic and proxy references */ 9567db96d56Sopenharmony_ci if (*list != NULL && (*list)->wr_callback == NULL) { 9577db96d56Sopenharmony_ci clear_weakref(*list); 9587db96d56Sopenharmony_ci if (*list != NULL && (*list)->wr_callback == NULL) 9597db96d56Sopenharmony_ci clear_weakref(*list); 9607db96d56Sopenharmony_ci } 9617db96d56Sopenharmony_ci if (*list != NULL) { 9627db96d56Sopenharmony_ci PyWeakReference *current = *list; 9637db96d56Sopenharmony_ci Py_ssize_t count = _PyWeakref_GetWeakrefCount(current); 9647db96d56Sopenharmony_ci PyObject *err_type, *err_value, *err_tb; 9657db96d56Sopenharmony_ci 9667db96d56Sopenharmony_ci PyErr_Fetch(&err_type, &err_value, &err_tb); 9677db96d56Sopenharmony_ci if (count == 1) { 9687db96d56Sopenharmony_ci PyObject *callback = current->wr_callback; 9697db96d56Sopenharmony_ci 9707db96d56Sopenharmony_ci current->wr_callback = NULL; 9717db96d56Sopenharmony_ci clear_weakref(current); 9727db96d56Sopenharmony_ci if (callback != NULL) { 9737db96d56Sopenharmony_ci if (Py_REFCNT((PyObject *)current) > 0) { 9747db96d56Sopenharmony_ci handle_callback(current, callback); 9757db96d56Sopenharmony_ci } 9767db96d56Sopenharmony_ci Py_DECREF(callback); 9777db96d56Sopenharmony_ci } 9787db96d56Sopenharmony_ci } 9797db96d56Sopenharmony_ci else { 9807db96d56Sopenharmony_ci PyObject *tuple; 9817db96d56Sopenharmony_ci Py_ssize_t i = 0; 9827db96d56Sopenharmony_ci 9837db96d56Sopenharmony_ci tuple = PyTuple_New(count * 2); 9847db96d56Sopenharmony_ci if (tuple == NULL) { 9857db96d56Sopenharmony_ci _PyErr_ChainExceptions(err_type, err_value, err_tb); 9867db96d56Sopenharmony_ci return; 9877db96d56Sopenharmony_ci } 9887db96d56Sopenharmony_ci 9897db96d56Sopenharmony_ci for (i = 0; i < count; ++i) { 9907db96d56Sopenharmony_ci PyWeakReference *next = current->wr_next; 9917db96d56Sopenharmony_ci 9927db96d56Sopenharmony_ci if (Py_REFCNT((PyObject *)current) > 0) { 9937db96d56Sopenharmony_ci Py_INCREF(current); 9947db96d56Sopenharmony_ci PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current); 9957db96d56Sopenharmony_ci PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback); 9967db96d56Sopenharmony_ci } 9977db96d56Sopenharmony_ci else { 9987db96d56Sopenharmony_ci Py_DECREF(current->wr_callback); 9997db96d56Sopenharmony_ci } 10007db96d56Sopenharmony_ci current->wr_callback = NULL; 10017db96d56Sopenharmony_ci clear_weakref(current); 10027db96d56Sopenharmony_ci current = next; 10037db96d56Sopenharmony_ci } 10047db96d56Sopenharmony_ci for (i = 0; i < count; ++i) { 10057db96d56Sopenharmony_ci PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1); 10067db96d56Sopenharmony_ci 10077db96d56Sopenharmony_ci /* The tuple may have slots left to NULL */ 10087db96d56Sopenharmony_ci if (callback != NULL) { 10097db96d56Sopenharmony_ci PyObject *item = PyTuple_GET_ITEM(tuple, i * 2); 10107db96d56Sopenharmony_ci handle_callback((PyWeakReference *)item, callback); 10117db96d56Sopenharmony_ci } 10127db96d56Sopenharmony_ci } 10137db96d56Sopenharmony_ci Py_DECREF(tuple); 10147db96d56Sopenharmony_ci } 10157db96d56Sopenharmony_ci assert(!PyErr_Occurred()); 10167db96d56Sopenharmony_ci PyErr_Restore(err_type, err_value, err_tb); 10177db96d56Sopenharmony_ci } 10187db96d56Sopenharmony_ci} 1019