@@ -171,32 +171,45 @@ enum_traverse(PyObject *op, visitproc visit, void *arg)
171
171
return 0 ;
172
172
}
173
173
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
+
174
195
static PyObject *
175
196
enum_next_long (enumobject * en , PyObject * next_item )
176
197
{
177
198
PyObject * result = en -> en_result ;
178
199
PyObject * next_index ;
179
- PyObject * stepped_up ;
180
200
PyObject * old_index ;
181
201
PyObject * old_item ;
182
202
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 ) {
194
208
Py_DECREF (next_item );
195
209
return NULL ;
196
210
}
197
- en -> en_longindex = stepped_up ;
198
211
199
- if (Py_REFCNT (result ) == 1 ) {
212
+ if (_PyObject_IsUniquelyReferenced (result )) {
200
213
Py_INCREF (result );
201
214
old_index = PyTuple_GET_ITEM (result , 0 );
202
215
old_item = PyTuple_GET_ITEM (result , 1 );
@@ -237,17 +250,18 @@ enum_next(PyObject *op)
237
250
if (next_item == NULL )
238
251
return NULL ;
239
252
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 )
241
255
return enum_next_long (en , next_item );
242
256
243
- next_index = PyLong_FromSsize_t (en -> en_index );
257
+ next_index = PyLong_FromSsize_t (en_index );
244
258
if (next_index == NULL ) {
245
259
Py_DECREF (next_item );
246
260
return NULL ;
247
261
}
248
- en -> en_index ++ ;
262
+ FT_ATOMIC_STORE_SSIZE_RELAXED ( en -> en_index , en_index + 1 ) ;
249
263
250
- if (Py_REFCNT (result ) == 1 ) {
264
+ if (_PyObject_IsUniquelyReferenced (result )) {
251
265
Py_INCREF (result );
252
266
old_index = PyTuple_GET_ITEM (result , 0 );
253
267
old_item = PyTuple_GET_ITEM (result , 1 );
@@ -277,10 +291,14 @@ static PyObject *
277
291
enum_reduce (PyObject * op , PyObject * Py_UNUSED (ignored ))
278
292
{
279
293
enumobject * en = _enumobject_CAST (op );
294
+ PyObject * result ;
295
+ Py_BEGIN_CRITICAL_SECTION (en );
280
296
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 );
282
298
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 ;
284
302
}
285
303
286
304
PyDoc_STRVAR (reduce_doc , "Return state information for pickling." );
0 commit comments