@@ -9,7 +9,35 @@ extern "C" {
99#endif
1010
1111#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION()
12+ #include "pycore_lock.h"
1213#include "pycore_object.h" // _Py_REF_IS_MERGED()
14+ #include "pycore_pyatomic_ft_wrappers.h"
15+
16+ #ifdef Py_GIL_DISABLED
17+
18+ #define WEAKREF_LIST_LOCK (obj ) \
19+ _PyInterpreterState_GET() \
20+ ->weakref_locks[((uintptr_t)obj) % NUM_WEAKREF_LIST_LOCKS]
21+
22+ // Lock using the referenced object
23+ #define LOCK_WEAKREFS (obj ) \
24+ PyMutex_LockFlags(&WEAKREF_LIST_LOCK(obj), _Py_LOCK_DONT_DETACH)
25+ #define UNLOCK_WEAKREFS (obj ) PyMutex_Unlock(&WEAKREF_LIST_LOCK(obj))
26+
27+ // Lock using a weakref
28+ #define LOCK_WEAKREFS_FOR_WR (wr ) \
29+ PyMutex_LockFlags(wr->weakrefs_lock, _Py_LOCK_DONT_DETACH)
30+ #define UNLOCK_WEAKREFS_FOR_WR (wr ) PyMutex_Unlock(wr->weakrefs_lock)
31+
32+ #else
33+
34+ #define LOCK_WEAKREFS (obj )
35+ #define UNLOCK_WEAKREFS (obj )
36+
37+ #define LOCK_WEAKREFS_FOR_WR (wr )
38+ #define UNLOCK_WEAKREFS_FOR_WR (wr )
39+
40+ #endif
1341
1442static inline int _is_dead (PyObject * obj )
1543{
@@ -30,53 +58,64 @@ static inline int _is_dead(PyObject *obj)
3058static inline PyObject * _PyWeakref_GET_REF (PyObject * ref_obj )
3159{
3260 assert (PyWeakref_Check (ref_obj ));
33- PyObject * ret = NULL ;
34- Py_BEGIN_CRITICAL_SECTION (ref_obj );
3561 PyWeakReference * ref = _Py_CAST (PyWeakReference * , ref_obj );
36- PyObject * obj = ref -> wr_object ;
3762
63+ PyObject * obj = FT_ATOMIC_LOAD_PTR (ref -> wr_object );
3864 if (obj == Py_None ) {
3965 // clear_weakref() was called
40- goto end ;
66+ return NULL ;
4167 }
4268
43- if (_is_dead (obj )) {
44- goto end ;
69+ LOCK_WEAKREFS (obj );
70+ #ifdef Py_GIL_DISABLED
71+ if (ref -> wr_object == Py_None ) {
72+ // clear_weakref() was called
73+ UNLOCK_WEAKREFS (obj );
74+ return NULL ;
4575 }
46- #if !defined(Py_GIL_DISABLED )
47- assert (Py_REFCNT (obj ) > 0 );
4876#endif
49- ret = Py_NewRef (obj );
50- end :
51- Py_END_CRITICAL_SECTION ();
52- return ret ;
77+ if (_Py_TryIncref (obj )) {
78+ UNLOCK_WEAKREFS (obj );
79+ return obj ;
80+ }
81+ UNLOCK_WEAKREFS (obj );
82+ return NULL ;
5383}
5484
5585static inline int _PyWeakref_IS_DEAD (PyObject * ref_obj )
5686{
5787 assert (PyWeakref_Check (ref_obj ));
5888 int ret = 0 ;
59- Py_BEGIN_CRITICAL_SECTION (ref_obj );
6089 PyWeakReference * ref = _Py_CAST (PyWeakReference * , ref_obj );
61- PyObject * obj = ref -> wr_object ;
90+ PyObject * obj = FT_ATOMIC_LOAD_PTR ( ref -> wr_object ) ;
6291 if (obj == Py_None ) {
6392 // clear_weakref() was called
6493 ret = 1 ;
6594 }
6695 else {
96+ LOCK_WEAKREFS (obj );
6797 // See _PyWeakref_GET_REF() for the rationale of this test
98+ #ifdef Py_GIL_DISABLED
99+ ret = (ref -> wr_object == Py_None ) || _is_dead (obj );
100+ #else
68101 ret = _is_dead (obj );
102+ #endif
103+ UNLOCK_WEAKREFS (obj );
69104 }
70- Py_END_CRITICAL_SECTION ();
71105 return ret ;
72106}
73107
74- extern Py_ssize_t _PyWeakref_GetWeakrefCount (PyWeakReference * head );
108+ extern Py_ssize_t _PyWeakref_GetWeakrefCount (PyObject * obj );
109+
110+ // Clear all the weak references to obj but leave their callbacks uncalled and
111+ // intact.
112+ extern void _PyWeakref_ClearWeakRefsExceptCallbacks (PyObject * obj );
75113
76114extern void _PyWeakref_ClearRef (PyWeakReference * self );
77115
116+ PyAPI_FUNC (int ) _PyWeakref_IsDead (PyObject * weakref );
117+
78118#ifdef __cplusplus
79119}
80120#endif
81121#endif /* !Py_INTERNAL_WEAKREF_H */
82-
0 commit comments