Skip to content

Commit 22a9ab2

Browse files
committed
Merge branch 'colesbury→iterator-nogil-threadsafety' into clone_of_pr5972
2 parents 648b05f + dc8e35c commit 22a9ab2

File tree

3 files changed

+27
-11
lines changed

3 files changed

+27
-11
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ jobs:
8484
python-version: '3.12'
8585
cmake-args: -DPYBIND11_TEST_SMART_HOLDER=ON -DPYBIND11_SIMPLE_GIL_MANAGEMENT=ON
8686
- runs-on: ubuntu-latest
87-
python-version: '3.13t'
87+
python-version: '3.14t'
8888
cmake-args: -DCMAKE_CXX_STANDARD=20 -DPYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION=ON
8989
- runs-on: ubuntu-latest
9090
python-version: '3.14'
@@ -102,12 +102,12 @@ jobs:
102102
- runs-on: macos-15-intel
103103
python-version: '3.11'
104104
cmake-args: -DPYBIND11_TEST_SMART_HOLDER=ON
105+
- runs-on: macos-15-intel
106+
python-version: '3.13'
107+
cmake-args: -DCMAKE_CXX_STANDARD=11
105108
- runs-on: macos-latest
106109
python-version: '3.12'
107110
cmake-args: -DCMAKE_CXX_STANDARD=17 -DPYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION=ON
108-
- runs-on: macos-15-intel
109-
python-version: '3.13t'
110-
cmake-args: -DCMAKE_CXX_STANDARD=11
111111
- runs-on: macos-latest
112112
python-version: '3.14t'
113113
cmake-args: -DCMAKE_CXX_STANDARD=20
@@ -138,9 +138,6 @@ jobs:
138138
- runs-on: windows-2022
139139
python-version: '3.13'
140140
cmake-args: -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebugDLL
141-
- runs-on: windows-latest
142-
python-version: '3.13t'
143-
cmake-args: -DCMAKE_CXX_STANDARD=17
144141
- runs-on: windows-latest
145142
python-version: '3.14'
146143
cmake-args: -DCMAKE_CXX_STANDARD=20
@@ -240,7 +237,7 @@ jobs:
240237

241238

242239
manylinux:
243-
name: Manylinux on 🐍 3.13t • GIL
240+
name: Manylinux on 🐍 3.14t
244241
if: github.event.pull_request.draft == false
245242
runs-on: ubuntu-latest
246243
timeout-minutes: 40
@@ -257,7 +254,7 @@ jobs:
257254
run: uv tool install ninja
258255

259256
- name: Configure via preset
260-
run: cmake --preset venv -DPYBIND11_CREATE_WITH_UV=python3.13t
257+
run: cmake --preset venv -DPYBIND11_CREATE_WITH_UV=python3.14t
261258

262259
- name: Build C++11
263260
run: cmake --build --preset venv

include/pybind11/detail/internals.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ using instance_map = std::unordered_multimap<const void *, instance *>;
230230
#ifdef Py_GIL_DISABLED
231231
// Wrapper around PyMutex to provide BasicLockable semantics
232232
class pymutex {
233+
friend class pycritical_section;
233234
PyMutex mutex;
234235

235236
public:
@@ -238,6 +239,23 @@ class pymutex {
238239
void unlock() { PyMutex_Unlock(&mutex); }
239240
};
240241

242+
class pycritical_section {
243+
pymutex &mutex;
244+
PyCriticalSection cs;
245+
246+
public:
247+
explicit pycritical_section(pymutex &m) : mutex(m) {
248+
PyCriticalSection_BeginMutex(&cs, &mutex.mutex);
249+
}
250+
~pycritical_section() { PyCriticalSection_End(&cs); }
251+
252+
// Non-copyable and non-movable to prevent double-unlock
253+
pycritical_section(const pycritical_section &) = delete;
254+
pycritical_section &operator=(const pycritical_section &) = delete;
255+
pycritical_section(pycritical_section &&) = delete;
256+
pycritical_section &operator=(pycritical_section &&) = delete;
257+
};
258+
241259
// Instance map shards are used to reduce mutex contention in free-threaded Python.
242260
struct instance_map_shard {
243261
instance_map registered_instances;
@@ -888,7 +906,7 @@ inline local_internals &get_local_internals() {
888906
}
889907

890908
#ifdef Py_GIL_DISABLED
891-
# define PYBIND11_LOCK_INTERNALS(internals) std::unique_lock<pymutex> lock((internals).mutex)
909+
# define PYBIND11_LOCK_INTERNALS(internals) pycritical_section lock((internals).mutex)
892910
#else
893911
# define PYBIND11_LOCK_INTERNALS(internals)
894912
#endif
@@ -917,7 +935,7 @@ inline auto with_exception_translators(const F &cb)
917935
get_local_internals().registered_exception_translators)) {
918936
auto &internals = get_internals();
919937
#ifdef Py_GIL_DISABLED
920-
std::unique_lock<pymutex> lock((internals).exception_translator_mutex);
938+
pycritical_section lock((internals).exception_translator_mutex);
921939
#endif
922940
auto &local_internals = get_local_internals();
923941
return cb(internals.registered_exception_translators,

include/pybind11/pybind11.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3173,6 +3173,7 @@ iterator make_iterator_impl(Iterator first, Sentinel last, Extra &&...extra) {
31733173
using state = detail::iterator_state<Access, Policy, Iterator, Sentinel, ValueType, Extra...>;
31743174
// TODO: state captures only the types of Extra, not the values
31753175

3176+
PYBIND11_LOCK_INTERNALS(get_internals());
31763177
if (!detail::get_type_info(typeid(state), false)) {
31773178
class_<state>(handle(), "iterator", pybind11::module_local())
31783179
.def(

0 commit comments

Comments
 (0)