@@ -171,32 +171,45 @@ enum_traverse(PyObject *op, visitproc visit, void *arg)
171171 return 0 ;
172172}
173173
174+ // increment en_longindex with lock held, return the next index to be used
175+ // or NULL on error
176+ static inline PyObject *
177+ increment_longindex_lock_held (enumobject * en )
178+ {
179+ PyObject * next_index = en -> en_longindex ;
180+ if (next_index == NULL ) {
181+ next_index = PyLong_FromSsize_t (PY_SSIZE_T_MAX );
182+ if (next_index == NULL ) {
183+ return NULL ;
184+ }
185+ }
186+ assert (next_index != NULL );
187+ PyObject * stepped_up = PyNumber_Add (next_index , en -> one );
188+ if (stepped_up == NULL ) {
189+ return NULL ;
190+ }
191+ en -> en_longindex = stepped_up ;
192+ return next_index ;
193+ }
194+
174195static PyObject *
175196enum_next_long (enumobject * en , PyObject * next_item )
176197{
177198 PyObject * result = en -> en_result ;
178199 PyObject * next_index ;
179- PyObject * stepped_up ;
180200 PyObject * old_index ;
181201 PyObject * old_item ;
182202
183- if (en -> en_longindex == NULL ) {
184- en -> en_longindex = PyLong_FromSsize_t (PY_SSIZE_T_MAX );
185- if (en -> en_longindex == NULL ) {
186- Py_DECREF (next_item );
187- return NULL ;
188- }
189- }
190- next_index = en -> en_longindex ;
191- assert (next_index != NULL );
192- stepped_up = PyNumber_Add (next_index , en -> one );
193- if (stepped_up == NULL ) {
203+
204+ Py_BEGIN_CRITICAL_SECTION (en );
205+ next_index = increment_longindex_lock_held (en );
206+ Py_END_CRITICAL_SECTION ();
207+ if (next_index == NULL ) {
194208 Py_DECREF (next_item );
195209 return NULL ;
196210 }
197- en -> en_longindex = stepped_up ;
198211
199- if (Py_REFCNT (result ) == 1 ) {
212+ if (_PyObject_IsUniquelyReferenced (result )) {
200213 Py_INCREF (result );
201214 old_index = PyTuple_GET_ITEM (result , 0 );
202215 old_item = PyTuple_GET_ITEM (result , 1 );
@@ -237,17 +250,18 @@ enum_next(PyObject *op)
237250 if (next_item == NULL )
238251 return NULL ;
239252
240- if (en -> en_index == PY_SSIZE_T_MAX )
253+ Py_ssize_t en_index = FT_ATOMIC_LOAD_SSIZE_RELAXED (en -> en_index );
254+ if (en_index == PY_SSIZE_T_MAX )
241255 return enum_next_long (en , next_item );
242256
243- next_index = PyLong_FromSsize_t (en -> en_index );
257+ next_index = PyLong_FromSsize_t (en_index );
244258 if (next_index == NULL ) {
245259 Py_DECREF (next_item );
246260 return NULL ;
247261 }
248- en -> en_index ++ ;
262+ FT_ATOMIC_STORE_SSIZE_RELAXED ( en -> en_index , en_index + 1 ) ;
249263
250- if (Py_REFCNT (result ) == 1 ) {
264+ if (_PyObject_IsUniquelyReferenced (result )) {
251265 Py_INCREF (result );
252266 old_index = PyTuple_GET_ITEM (result , 0 );
253267 old_item = PyTuple_GET_ITEM (result , 1 );
@@ -277,10 +291,14 @@ static PyObject *
277291enum_reduce (PyObject * op , PyObject * Py_UNUSED (ignored ))
278292{
279293 enumobject * en = _enumobject_CAST (op );
294+ PyObject * result ;
295+ Py_BEGIN_CRITICAL_SECTION (en );
280296 if (en -> en_longindex != NULL )
281- return Py_BuildValue ("O(OO)" , Py_TYPE (en ), en -> en_sit , en -> en_longindex );
297+ result = Py_BuildValue ("O(OO)" , Py_TYPE (en ), en -> en_sit , en -> en_longindex );
282298 else
283- return Py_BuildValue ("O(On)" , Py_TYPE (en ), en -> en_sit , en -> en_index );
299+ result = Py_BuildValue ("O(On)" , Py_TYPE (en ), en -> en_sit , en -> en_index );
300+ Py_END_CRITICAL_SECTION ();
301+ return result ;
284302}
285303
286304PyDoc_STRVAR (reduce_doc , "Return state information for pickling." );
0 commit comments