Skip to content

Commit 3c03084

Browse files
committed
Don't use atomics for iteratio and allow multiple threads to race on values seen
1 parent 3618de1 commit 3c03084

File tree

1 file changed

+10
-23
lines changed

1 file changed

+10
-23
lines changed

Objects/dictobject.c

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4930,7 +4930,7 @@ dictiter_iternext_threadsafe(PyDictObject *d, PyObject *self,
49304930

49314931
ensure_shared_on_read(d);
49324932

4933-
Py_ssize_t start_pos = i = _Py_atomic_load_ssize_relaxed(&di->di_pos);
4933+
i = _Py_atomic_load_ssize_relaxed(&di->di_pos);
49344934
k = _Py_atomic_load_ptr_relaxed(&d->ma_keys);
49354935
assert(i >= 0);
49364936
if (_PyDict_HasSplitTable(d)) {
@@ -4990,20 +4990,13 @@ dictiter_iternext_threadsafe(PyDictObject *d, PyObject *self,
49904990
}
49914991
}
49924992
// We found an element (key), but did not expect it
4993-
if (_Py_atomic_load_ssize_relaxed(&di->len) == 0) {
4993+
Py_ssize_t len;
4994+
if ((len = _Py_atomic_load_ssize_relaxed(&di->len)) == 0) {
49944995
goto concurrent_modification;
49954996
}
4996-
if (!_Py_atomic_compare_exchange_ssize(&di->di_pos, &start_pos, i+1)) {
4997-
// We lost a race with someone else iterating...
4998-
if (out_key != NULL) {
4999-
Py_DECREF(*out_key);
5000-
}
5001-
if (out_value != NULL) {
5002-
Py_DECREF(*out_value);
5003-
}
5004-
goto try_locked;
5005-
}
5006-
_Py_atomic_add_ssize(&di->len, -1);
4997+
4998+
_Py_atomic_store_ssize_relaxed(&di->di_pos, i + 1);
4999+
_Py_atomic_store_ssize_relaxed(&di->len, len - 1);
50075000
return 1;
50085001

50095002
concurrent_modification:
@@ -5029,22 +5022,16 @@ static bool
50295022
acquire_iter_result(PyObject *result)
50305023
{
50315024
#ifdef Py_GIL_DISABLED
5032-
if (Py_REFCNT(result) == 1) {
5033-
Py_INCREF(result);
5034-
if (Py_REFCNT(result) == 2) {
5035-
return true;
5036-
}
5037-
Py_DECREF(result);
5038-
return false;
5039-
}
5040-
return false;
5025+
if (_Py_IsOwnedByCurrentThread(result) &&
5026+
result->ob_ref_local == 1 &&
5027+
_Py_atomic_load_ssize_relaxed(&result->ob_ref_shared) == 0) {
50415028
#else
50425029
if (Py_REFCNT(result) == 1) {
5030+
#endif
50435031
Py_INCREF(result);
50445032
return true;
50455033
}
50465034
return false;
5047-
#endif
50485035
}
50495036

50505037
static PyObject *

0 commit comments

Comments
 (0)