(root)/
Python-3.12.0/
Include/
cpython/
weakrefobject.h
       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  static inline PyObject* PyWeakref_GET_OBJECT(PyObject *ref_obj) {
      40      PyWeakReference *ref;
      41      PyObject *obj;
      42      assert(PyWeakref_Check(ref_obj));
      43      ref = _Py_CAST(PyWeakReference*, ref_obj);
      44      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      if (Py_REFCNT(obj) > 0) {
      52          return obj;
      53      }
      54      return Py_None;
      55  }
      56  #define PyWeakref_GET_OBJECT(ref) PyWeakref_GET_OBJECT(_PyObject_CAST(ref))