File indexing completed on 2025-11-19 09:50:52
0001 #ifndef Py_INTERNAL_WEAKREF_H
0002 #define Py_INTERNAL_WEAKREF_H
0003 #ifdef __cplusplus
0004 extern "C" {
0005 #endif
0006
0007 #ifndef Py_BUILD_CORE
0008 # error "this header requires Py_BUILD_CORE define"
0009 #endif
0010
0011 #include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION()
0012 #include "pycore_lock.h"
0013 #include "pycore_object.h" // _Py_REF_IS_MERGED()
0014 #include "pycore_pyatomic_ft_wrappers.h"
0015
0016 #ifdef Py_GIL_DISABLED
0017
0018 #define WEAKREF_LIST_LOCK(obj) \
0019 _PyInterpreterState_GET() \
0020 ->weakref_locks[((uintptr_t)obj) % NUM_WEAKREF_LIST_LOCKS]
0021
0022
0023 #define LOCK_WEAKREFS(obj) \
0024 PyMutex_LockFlags(&WEAKREF_LIST_LOCK(obj), _Py_LOCK_DONT_DETACH)
0025 #define UNLOCK_WEAKREFS(obj) PyMutex_Unlock(&WEAKREF_LIST_LOCK(obj))
0026
0027
0028 #define LOCK_WEAKREFS_FOR_WR(wr) \
0029 PyMutex_LockFlags(wr->weakrefs_lock, _Py_LOCK_DONT_DETACH)
0030 #define UNLOCK_WEAKREFS_FOR_WR(wr) PyMutex_Unlock(wr->weakrefs_lock)
0031
0032 #else
0033
0034 #define LOCK_WEAKREFS(obj)
0035 #define UNLOCK_WEAKREFS(obj)
0036
0037 #define LOCK_WEAKREFS_FOR_WR(wr)
0038 #define UNLOCK_WEAKREFS_FOR_WR(wr)
0039
0040 #endif
0041
0042 static inline int _is_dead(PyObject *obj)
0043 {
0044
0045
0046
0047
0048
0049
0050 #if defined(Py_GIL_DISABLED)
0051 Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&obj->ob_ref_shared);
0052 return shared == _Py_REF_SHARED(0, _Py_REF_MERGED);
0053 #else
0054 return (Py_REFCNT(obj) == 0);
0055 #endif
0056 }
0057
0058 static inline PyObject* _PyWeakref_GET_REF(PyObject *ref_obj)
0059 {
0060 assert(PyWeakref_Check(ref_obj));
0061 PyWeakReference *ref = _Py_CAST(PyWeakReference*, ref_obj);
0062
0063 PyObject *obj = FT_ATOMIC_LOAD_PTR(ref->wr_object);
0064 if (obj == Py_None) {
0065
0066 return NULL;
0067 }
0068
0069 LOCK_WEAKREFS(obj);
0070 #ifdef Py_GIL_DISABLED
0071 if (ref->wr_object == Py_None) {
0072
0073 UNLOCK_WEAKREFS(obj);
0074 return NULL;
0075 }
0076 #endif
0077 if (_Py_TryIncref(obj)) {
0078 UNLOCK_WEAKREFS(obj);
0079 return obj;
0080 }
0081 UNLOCK_WEAKREFS(obj);
0082 return NULL;
0083 }
0084
0085 static inline int _PyWeakref_IS_DEAD(PyObject *ref_obj)
0086 {
0087 assert(PyWeakref_Check(ref_obj));
0088 int ret = 0;
0089 PyWeakReference *ref = _Py_CAST(PyWeakReference*, ref_obj);
0090 PyObject *obj = FT_ATOMIC_LOAD_PTR(ref->wr_object);
0091 if (obj == Py_None) {
0092
0093 ret = 1;
0094 }
0095 else {
0096 LOCK_WEAKREFS(obj);
0097
0098 #ifdef Py_GIL_DISABLED
0099 ret = (ref->wr_object == Py_None) || _is_dead(obj);
0100 #else
0101 ret = _is_dead(obj);
0102 #endif
0103 UNLOCK_WEAKREFS(obj);
0104 }
0105 return ret;
0106 }
0107
0108 extern Py_ssize_t _PyWeakref_GetWeakrefCount(PyObject *obj);
0109
0110
0111
0112 extern void _PyWeakref_ClearWeakRefsNoCallbacks(PyObject *obj);
0113
0114 PyAPI_FUNC(int) _PyWeakref_IsDead(PyObject *weakref);
0115
0116 #ifdef __cplusplus
0117 }
0118 #endif
0119 #endif