Branch data Line data Source code
1 : : #ifndef Py_CPYTHON_WEAKREFOBJECT_H 2 : : # error "this header file must not be included directly" 3 : : #endif 4 : : 5 : : /* PyWeakReference is the base struct for the Python ReferenceType, ProxyType, 6 : : * and CallableProxyType. 7 : : */ 8 : : struct _PyWeakReference { 9 : : PyObject_HEAD 10 : : 11 : : /* The object to which this is a weak reference, or Py_None if none. 12 : : * Note that this is a stealth reference: wr_object's refcount is 13 : : * not incremented to reflect this pointer. 14 : : */ 15 : : PyObject *wr_object; 16 : : 17 : : /* A callable to invoke when wr_object dies, or NULL if none. */ 18 : : PyObject *wr_callback; 19 : : 20 : : /* A cache for wr_object's hash code. As usual for hashes, this is -1 21 : : * if the hash code isn't known yet. 22 : : */ 23 : : Py_hash_t hash; 24 : : 25 : : /* If wr_object is weakly referenced, wr_object has a doubly-linked NULL- 26 : : * terminated list of weak references to it. These are the list pointers. 27 : : * If wr_object goes away, wr_object is set to Py_None, and these pointers 28 : : * have no meaning then. 29 : : */ 30 : : PyWeakReference *wr_prev; 31 : : PyWeakReference *wr_next; 32 : : vectorcallfunc vectorcall; 33 : : }; 34 : : 35 : : PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head); 36 : : 37 : : PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self); 38 : : 39 : 286714 : static inline PyObject* PyWeakref_GET_OBJECT(PyObject *ref_obj) { 40 : : PyWeakReference *ref; 41 : : PyObject *obj; 42 : : assert(PyWeakref_Check(ref_obj)); 43 : 286714 : ref = _Py_CAST(PyWeakReference*, ref_obj); 44 : 286714 : obj = ref->wr_object; 45 : : // Explanation for the Py_REFCNT() check: when a weakref's target is part 46 : : // of a long chain of deallocations which triggers the trashcan mechanism, 47 : : // clearing the weakrefs can be delayed long after the target's refcount 48 : : // has dropped to zero. In the meantime, code accessing the weakref will 49 : : // be able to "see" the target object even though it is supposed to be 50 : : // unreachable. See issue gh-60806. 51 [ + - ]: 286714 : if (Py_REFCNT(obj) > 0) { 52 : 286714 : return obj; 53 : : } 54 : 0 : return Py_None; 55 : : } 56 : : #define PyWeakref_GET_OBJECT(ref) PyWeakref_GET_OBJECT(_PyObject_CAST(ref))