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