Coverage Report

Created: 2025-07-04 06:49

/src/cpython-install/include/python3.15/cpython/weakrefobject.h
Line
Count
Source (jump to first uncovered line)
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
#ifdef Py_GIL_DISABLED
35
    /* Pointer to the lock used when clearing in free-threaded builds.
36
     * Normally this can be derived from wr_object, but in some cases we need
37
     * to lock after wr_object has been set to Py_None.
38
     */
39
    PyMutex *weakrefs_lock;
40
#endif
41
};
42
43
PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self);
44
45
#define _PyWeakref_CAST(op) \
46
    (assert(PyWeakref_Check(op)), _Py_CAST(PyWeakReference*, (op)))
47
48
// Test if a weak reference is dead.
49
PyAPI_FUNC(int) PyWeakref_IsDead(PyObject *ref);
50
51
Py_DEPRECATED(3.13) static inline PyObject* PyWeakref_GET_OBJECT(PyObject *ref_obj)
52
0
{
53
0
    PyWeakReference *ref = _PyWeakref_CAST(ref_obj);
54
0
    PyObject *obj = ref->wr_object;
55
0
    // Explanation for the Py_REFCNT() check: when a weakref's target is part
56
0
    // of a long chain of deallocations which triggers the trashcan mechanism,
57
0
    // clearing the weakrefs can be delayed long after the target's refcount
58
0
    // has dropped to zero.  In the meantime, code accessing the weakref will
59
0
    // be able to "see" the target object even though it is supposed to be
60
0
    // unreachable.  See issue gh-60806.
61
0
    if (Py_REFCNT(obj) > 0) {
62
0
        return obj;
63
0
    }
64
0
    return Py_None;
65
0
}
66
#define PyWeakref_GET_OBJECT(ref) PyWeakref_GET_OBJECT(_PyObject_CAST(ref))