jpayne@69: /* Weak references objects for Python. */ jpayne@69: jpayne@69: #ifndef Py_WEAKREFOBJECT_H jpayne@69: #define Py_WEAKREFOBJECT_H jpayne@69: #ifdef __cplusplus jpayne@69: extern "C" { jpayne@69: #endif jpayne@69: jpayne@69: jpayne@69: typedef struct _PyWeakReference PyWeakReference; jpayne@69: jpayne@69: /* PyWeakReference is the base struct for the Python ReferenceType, ProxyType, jpayne@69: * and CallableProxyType. jpayne@69: */ jpayne@69: #ifndef Py_LIMITED_API jpayne@69: struct _PyWeakReference { jpayne@69: PyObject_HEAD jpayne@69: jpayne@69: /* The object to which this is a weak reference, or Py_None if none. jpayne@69: * Note that this is a stealth reference: wr_object's refcount is jpayne@69: * not incremented to reflect this pointer. jpayne@69: */ jpayne@69: PyObject *wr_object; jpayne@69: jpayne@69: /* A callable to invoke when wr_object dies, or NULL if none. */ jpayne@69: PyObject *wr_callback; jpayne@69: jpayne@69: /* A cache for wr_object's hash code. As usual for hashes, this is -1 jpayne@69: * if the hash code isn't known yet. jpayne@69: */ jpayne@69: Py_hash_t hash; jpayne@69: jpayne@69: /* If wr_object is weakly referenced, wr_object has a doubly-linked NULL- jpayne@69: * terminated list of weak references to it. These are the list pointers. jpayne@69: * If wr_object goes away, wr_object is set to Py_None, and these pointers jpayne@69: * have no meaning then. jpayne@69: */ jpayne@69: PyWeakReference *wr_prev; jpayne@69: PyWeakReference *wr_next; jpayne@69: }; jpayne@69: #endif jpayne@69: jpayne@69: PyAPI_DATA(PyTypeObject) _PyWeakref_RefType; jpayne@69: PyAPI_DATA(PyTypeObject) _PyWeakref_ProxyType; jpayne@69: PyAPI_DATA(PyTypeObject) _PyWeakref_CallableProxyType; jpayne@69: jpayne@69: #define PyWeakref_CheckRef(op) PyObject_TypeCheck(op, &_PyWeakref_RefType) jpayne@69: #define PyWeakref_CheckRefExact(op) \ jpayne@69: (Py_TYPE(op) == &_PyWeakref_RefType) jpayne@69: #define PyWeakref_CheckProxy(op) \ jpayne@69: ((Py_TYPE(op) == &_PyWeakref_ProxyType) || \ jpayne@69: (Py_TYPE(op) == &_PyWeakref_CallableProxyType)) jpayne@69: jpayne@69: #define PyWeakref_Check(op) \ jpayne@69: (PyWeakref_CheckRef(op) || PyWeakref_CheckProxy(op)) jpayne@69: jpayne@69: jpayne@69: PyAPI_FUNC(PyObject *) PyWeakref_NewRef(PyObject *ob, jpayne@69: PyObject *callback); jpayne@69: PyAPI_FUNC(PyObject *) PyWeakref_NewProxy(PyObject *ob, jpayne@69: PyObject *callback); jpayne@69: PyAPI_FUNC(PyObject *) PyWeakref_GetObject(PyObject *ref); jpayne@69: jpayne@69: #ifndef Py_LIMITED_API jpayne@69: PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head); jpayne@69: jpayne@69: PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self); jpayne@69: #endif jpayne@69: jpayne@69: /* Explanation for the Py_REFCNT() check: when a weakref's target is part jpayne@69: of a long chain of deallocations which triggers the trashcan mechanism, jpayne@69: clearing the weakrefs can be delayed long after the target's refcount jpayne@69: has dropped to zero. In the meantime, code accessing the weakref will jpayne@69: be able to "see" the target object even though it is supposed to be jpayne@69: unreachable. See issue #16602. */ jpayne@69: jpayne@69: #define PyWeakref_GET_OBJECT(ref) \ jpayne@69: (Py_REFCNT(((PyWeakReference *)(ref))->wr_object) > 0 \ jpayne@69: ? ((PyWeakReference *)(ref))->wr_object \ jpayne@69: : Py_None) jpayne@69: jpayne@69: jpayne@69: #ifdef __cplusplus jpayne@69: } jpayne@69: #endif jpayne@69: #endif /* !Py_WEAKREFOBJECT_H */