1
+ /* Copyright (c) 2019, Oracle and/or its affiliates.
2
+ * Copyright (C) 1996-2017 Python Software Foundation
3
+ *
4
+ * Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
5
+ */
6
+ /* Weak references objects for Python. */
7
+
8
+ #ifndef Py_WEAKREFOBJECT_H
9
+ #define Py_WEAKREFOBJECT_H
10
+ #ifdef __cplusplus
11
+ extern "C" {
12
+ #endif
13
+
14
+
15
+ typedef struct _PyWeakReference PyWeakReference ;
16
+
17
+ /* PyWeakReference is the base struct for the Python ReferenceType, ProxyType,
18
+ * and CallableProxyType.
19
+ */
20
+ #ifndef Py_LIMITED_API
21
+ struct _PyWeakReference {
22
+ PyObject_HEAD
23
+
24
+ /* The object to which this is a weak reference, or Py_None if none.
25
+ * Note that this is a stealth reference: wr_object's refcount is
26
+ * not incremented to reflect this pointer.
27
+ */
28
+ PyObject * wr_object ;
29
+
30
+ /* A callable to invoke when wr_object dies, or NULL if none. */
31
+ PyObject * wr_callback ;
32
+
33
+ /* A cache for wr_object's hash code. As usual for hashes, this is -1
34
+ * if the hash code isn't known yet.
35
+ */
36
+ Py_hash_t hash ;
37
+
38
+ /* If wr_object is weakly referenced, wr_object has a doubly-linked NULL-
39
+ * terminated list of weak references to it. These are the list pointers.
40
+ * If wr_object goes away, wr_object is set to Py_None, and these pointers
41
+ * have no meaning then.
42
+ */
43
+ PyWeakReference * wr_prev ;
44
+ PyWeakReference * wr_next ;
45
+ };
46
+ #endif
47
+
48
+ PyAPI_DATA (PyTypeObject ) _PyWeakref_RefType ;
49
+ PyAPI_DATA (PyTypeObject ) _PyWeakref_ProxyType ;
50
+ PyAPI_DATA (PyTypeObject ) _PyWeakref_CallableProxyType ;
51
+
52
+ #define PyWeakref_CheckRef (op ) PyObject_TypeCheck(op, &_PyWeakref_RefType)
53
+ #define PyWeakref_CheckRefExact (op ) \
54
+ (Py_TYPE(op) == &_PyWeakref_RefType)
55
+ #define PyWeakref_CheckProxy (op ) \
56
+ ((Py_TYPE(op) == &_PyWeakref_ProxyType) || \
57
+ (Py_TYPE(op) == &_PyWeakref_CallableProxyType))
58
+
59
+ #define PyWeakref_Check (op ) \
60
+ (PyWeakref_CheckRef(op) || PyWeakref_CheckProxy(op))
61
+
62
+
63
+ PyAPI_FUNC (PyObject * ) PyWeakref_NewRef (PyObject * ob ,
64
+ PyObject * callback );
65
+ PyAPI_FUNC (PyObject * ) PyWeakref_NewProxy (PyObject * ob ,
66
+ PyObject * callback );
67
+ PyAPI_FUNC (PyObject * ) PyWeakref_GetObject (PyObject * ref );
68
+
69
+ #ifndef Py_LIMITED_API
70
+ PyAPI_FUNC (Py_ssize_t ) _PyWeakref_GetWeakrefCount (PyWeakReference * head );
71
+
72
+ PyAPI_FUNC (void ) _PyWeakref_ClearRef (PyWeakReference * self );
73
+ #endif
74
+
75
+ /* Explanation for the Py_REFCNT() check: when a weakref's target is part
76
+ of a long chain of deallocations which triggers the trashcan mechanism,
77
+ clearing the weakrefs can be delayed long after the target's refcount
78
+ has dropped to zero. In the meantime, code accessing the weakref will
79
+ be able to "see" the target object even though it is supposed to be
80
+ unreachable. See issue #16602. */
81
+
82
+ #define PyWeakref_GET_OBJECT (ref ) \
83
+ (Py_REFCNT(((PyWeakReference *)(ref))->wr_object) > 0 \
84
+ ? ((PyWeakReference *)(ref))->wr_object \
85
+ : Py_None)
86
+
87
+
88
+ #ifdef __cplusplus
89
+ }
90
+ #endif
91
+ #endif /* !Py_WEAKREFOBJECT_H */
0 commit comments