8000 make enum_next_long safe · python/cpython@30c575e · GitHub
[go: up one dir, main page]

Skip to content

Commit 30c575e

Browse files
committed
make enum_next_long safe
1 parent 546dddc commit 30c575e

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

Objects/enumobject.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -177,23 +177,34 @@ enum_next_long(enumobject *en, PyObject* next_item)
177177
PyObject *old_index;
178178
PyObject *old_item;
179179

180-
if (en->en_longindex == NULL) {
181-
en->en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX);
182-
if (en->en_longindex == NULL) {
180+
#ifdef Py_GIL_DISABLED
181+
// resets en->en_longindex to 0, but we will restore it later
182+
PyObject *en_longindex = ( PyObject *)_Py_atomic_exchange_ptr(&en->en_longindex, NULL);
183+
#else
184+
PyObject *en_longindex = en->en_longindex;
185+
#endif
186+
if (en_longindex == NULL) {
187+
en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX);
188+
if (en_longindex == NULL) {
183189
Py_DECREF(next_item);
184190
return NULL;
185191
}
186192
}
187-
next_index = en->en_longindex;
193+
next_index = en_longindex;
188194
assert(next_index != NULL);
189195
stepped_up = PyNumber_Add(next_index, en->one);
190196
if (stepped_up == NULL) {
191197
Py_DECREF(next_item);
192198
return NULL;
193199
}
200+
#ifdef Py_GIL_DISABLED
201+
PyObject *en_longindex_old = ( PyObject *)_Py_atomic_exchange_ptr(&en->en_longindex, stepped_up);
202+
Py_XDECREF(en_longindex_old);
203+
#else
194204
en->en_longindex = stepped_up;
205+
#endif
195206

196-
if (Py_REFCNT(result) == 1) {
207+
if (_PyObject_IsUniquelyReferenced(result)) {
197208
Py_INCREF(result);
198209
old_index = PyTuple_GET_ITEM(result, 0);
199210
old_item = PyTuple_GET_ITEM(result, 1);
@@ -233,17 +244,19 @@ enum_next(enumobject *en)
233244
if (next_item == NULL)
234245
return NULL;
235246

236-
if (en->en_index == PY_SSIZE_T_MAX)
247+
Py_ssize_t en_index = FT_ATOMIC_LOAD_SSIZE_RELAXED(en->en_index);
248+
if (en_index == PY_SSIZE_T_MAX)
237249
return enum_next_long(en, next_item);
238250

239-
next_index = PyLong_FromSsize_t(en->en_index);
251+
252+
next_index = PyLong_FromSsize_t(en_index);
240253
if (next_index == NULL) {
241254
Py_DECREF(next_item);
242255
return NULL;
243256
}
244-
en->en_index++;
257+
FT_ATOMIC_STORE_SSIZE_RELAXED(en->en_index, en_index + 1);
245258

246-
if (Py_REFCNT(result) == 1) {
259+
if (_PyObject_IsUniquelyReferenced(result)) {
247260
Py_INCREF(result);
248261
old_index = PyTuple_GET_ITEM(result, 0);
249262
old_item = PyTuple_GET_ITEM(result, 1);
@@ -272,10 +285,23 @@ enum_next(enumobject *en)
272285
static PyObject *
273286
enum_reduce(enumobject *en, PyObject *Py_UNUSED(ignored))
274287
{
275-
if (en->en_longindex != NULL)
276-
return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex);
277-
else
288+
#ifdef Py_GIL_DISABLED
289+
PyObject *en_longindex = ( PyObject *)_Py_atomic_exchange_ptr(&en->en_longindex, NULL);
290+
#else
291+
PyObject *en_longindex = en->en_longindex;
292+
#endif
293+
if (en_longindex != NULL) {
294+
PyObject *value = Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en_longindex);
295+
#ifdef Py_GIL_DISABLED
296+
// restore value of en->en_longindex
297+
PyObject *en_longindex_old = ( PyObject *)_Py_atomic_exchange_ptr(&en->en_longindex, en_longindex);
298+
Py_XDECREF(en_longindex_old);
299+
#endif
300+
return value;
301+
}
302+
else {
278303
return Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en->en_index);
304+
}
279305
}
280306

281307
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");

0 commit comments

Comments
 (0)
0