Closed
Description
Feature or enhancement
The set
object is not currently thread-safe in --disable-gil
builds. We should make it thread-safe by using the "critical section" API. to acquire the per-object locks around operations. There should be no effective change in the default build (i.e., with GIL) because critical sections are no-ops in the default build.
Notes:
- Unlike
dict
andlist
, I don't think it's worth the complexity to try to "optimistically avoid locking" around any set operation (exceptset_len
). We could consider doing this in the future if there is a performance justification, but not for 3.13. set_len
can avoid locking and instead use relaxed atomics for reading the "used" field. Note that writes to "used" should then also use relaxed atomics.- Some operations require locking two containers (like
set_merge
). Some of these will need refactorings so that the critical sections macros can be added in the correct places.
For context, here is the change from the nogil-3.12
fork: colesbury/nogil-3.12@4ca2924f0d. Note that the critical section API is slightly changed in 3.13 from nogil-3.12
; In 3.13 Py_BEGIN_CRITICAL_SECTION
takes a PyObject instead of a PyMutex.
TODO:
- Improve
set_init
(see gh-112069: Make sets thread-safe with the GIL disabled #113800 (comment)). We also want to avoid locking inset_init
if possible -
_PySet_NextEntry
-
setiter_iternext
Linked PRs
- gh-112069: Make sets thread-safe with the GIL disabled #113800
- gh-112069: Adapt set/frozenset methods to Argument Clinic #115112
- Revert "gh-112069: Make sets thread-safe with the GIL disabled (#113800)" #116525
- gh-112069: Make setiter_iternext to be thread-safe #117935
- gh-112069: Add _PySet_NextEntryRef to be thread-safe. #117990
- gh-112069: Make PySet_GET_SIZE to be atomic safe. #118053
- gh-112069: Do not require lock if the set has never been exposed. #118069