Make `list` objects thread-safe in `--disable-gil` builds

Feature or enhancement

I expect this to be implemented across multiple PRs.

For context, here is the change from the nogil-3.12 fork, but things might be done a bit differently in CPython 3.13: colesbury/nogil-3.12@df4c51f82b.

  • Most operations should acquire the list object lock using the critical section API.
  • Accessing a single element should optimistically avoid locking for performance
  • Iterators need some special handling
  • list.sort

Iterators

For performance reasons, we don't want to acquire locks while iterating over lists. This means that list iterators have a lesser notion of thread-safety: multiple threads concurrently using the same iterator should not crash but may revisit elements. We should make clear in the documentation that iterators are not generally thread-safe. From an implementation point of view, we should use relaxed atomics to update the it_index variable.

Additionally, we don't want to clear the it_seq reference to the list when the iterator is exhausted in --disable-gil builds. Doing so would pose thread-safety issues (in the "may segfault sense").

I don't expect this to pose any issues for real code. While it's fairly common to share lists between threads, it's rare to share the same iterator object between threads.

Linked PRs