4
4
#include "Python.h"
5
5
#include "pycore_abstract.h" // _PyNumber_Index()
6
6
#include "pycore_long.h" // _PyLong_IsNegative()
7
+ #include "pycore_object.h" // _Py_TryIncrefCompare(), FT_ATOMIC_*()
8
+ #include "pycore_critical_section.h"
7
9
8
10
11
+ static inline PyObject *
12
+ member_get_object (const char * addr , const char * obj_addr , PyMemberDef * l )
13
+ {
14
+ PyObject * v = FT_ATOMIC_LOAD_PTR (* (PyObject * * ) addr );
15
+ if (v == NULL ) {
16
+ PyErr_Format (PyExc_AttributeError ,
17
+ "'%T' object has no attribute '%s'" ,
18
+ (PyObject * )obj_addr , l -> name );
19
+ }
20
+ return v ;
21
+ }
22
+
9
23
PyObject *
10
24
PyMember_GetOne (const char * obj_addr , PyMemberDef * l )
11
25
{
@@ -75,15 +89,19 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
75
89
Py_INCREF (v );
76
90
break ;
77
91
case Py_T_OBJECT_EX :
78
- v = * (PyObject * * )addr ;
79
- if (v == NULL ) {
80
- PyObject * obj = (PyObject * )obj_addr ;
81
- PyTypeObject * tp = Py_TYPE (obj );
82
- PyErr_Format (PyExc_AttributeError ,
83
- "'%.200s' object has no attribute '%s'" ,
84
- tp -> tp_name , l -> name );
85
- }
92
+ v = member_get_object (addr , obj_addr , l );
93
+ #ifndef Py_GIL_DISABLED
86
94
Py_XINCREF (v );
95
+ #else
96
+ if (v != NULL ) {
97
+ if (!_Py_TryIncrefCompare ((PyObject * * ) addr , v )) {
98
+ Py_BEGIN_CRITICAL_SECTION ((PyObject * ) obj_addr );
99
+ v = member_get_object (addr , obj_addr , l );
100
+ Py_XINCREF (v );
101
+ Py_END_CRITICAL_SECTION ();
102
+ }
103
+ }
104
+ #endif
87
105
break ;
88
106
case Py_T_LONGLONG :
89
107
v = PyLong_FromLongLong (* (long long * )addr );
@@ -92,6 +110,7 @@ PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
92
110
v = PyLong_FromUnsignedLongLong (* (unsigned long long * )addr );
93
111
break ;
94
112
case _Py_T_NONE :
113
+ // doesn't require free-threading code path
95
114
v = Py_NewRef (Py_None );
96
115
break ;
97
116
default :
@@ -118,6 +137,9 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
118
137
return -1 ;
119
138
}
120
139
140
+ #ifdef Py_GIL_DISABLED
141
+ PyObject * obj = (PyObject * ) addr ;
142
+ #endif
121
143
addr += l -> offset ;
122
144
123
145
if ((l -> flags & Py_READONLY ))
@@ -281,8 +303,10 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
281
303
break ;
282
304
case _Py_T_OBJECT :
283
305
case Py_T_OBJECT_EX :
306
+ Py_BEGIN_CRITICAL_SECTION (obj );
284
307
oldv = * (PyObject * * )addr ;
285
- * (PyObject * * )addr = Py_XNewRef (v );
308
+ FT_ATOMIC_STORE_PTR_RELEASE (* (PyObject * * )addr , Py_XNewRef (v ));
309
+ Py_END_CRITICAL_SECTION ();
286
310
Py_XDECREF (oldv );
287
311
break ;
288
312
case Py_T_CHAR : {
0 commit comments