Use PyCriticalSection_BeginMutex instead of recursive mutex

This commit is contained in:
Sam Gross
2026-01-22 12:25:57 -05:00
parent fa039538d3
commit 70c2ffcb67

View File

@@ -230,6 +230,7 @@ using instance_map = std::unordered_multimap<const void *, instance *>;
#ifdef Py_GIL_DISABLED
// Wrapper around PyMutex to provide BasicLockable semantics
class pymutex {
friend class pycritical_section;
PyMutex mutex;
public:
@@ -238,29 +239,16 @@ public:
void unlock() { PyMutex_Unlock(&mutex); }
};
// A recursive mutex implementation using PyMutex
class pyrecursive_mutex {
PyMutex mutex;
std::atomic<uintptr_t> owner;
size_t lock_count;
class pycritical_section {
pymutex& mutex;
PyCriticalSection cs;
public:
pyrecursive_mutex() : mutex({}), owner(0), lock_count(0) {}
void lock() {
if (owner.load(std::memory_order_relaxed) == _Py_ThreadId()) {
++lock_count;
return;
}
PyMutex_Lock(&mutex);
owner.store(_Py_ThreadId(), std::memory_order_relaxed);
explicit pycritical_section(pymutex& m) : mutex(m) {
PyCriticalSection_BeginMutex(&cs, &mutex.mutex);
}
void unlock() {
if (lock_count > 0) {
--lock_count;
return;
}
owner.store(0, std::memory_order_relaxed);
PyMutex_Unlock(&mutex);
~pycritical_section() {
PyCriticalSection_End(&cs);
}
};
@@ -297,7 +285,7 @@ class loader_life_support;
/// `PYBIND11_INTERNALS_VERSION` must be incremented.
struct internals {
#ifdef Py_GIL_DISABLED
pyrecursive_mutex mutex;
pymutex mutex;
pymutex exception_translator_mutex;
#endif
#if PYBIND11_INTERNALS_VERSION >= 12
@@ -882,8 +870,7 @@ inline local_internals &get_local_internals() {
}
#ifdef Py_GIL_DISABLED
# define PYBIND11_LOCK_INTERNALS(internals) \
std::unique_lock<pyrecursive_mutex> lock((internals).mutex)
# define PYBIND11_LOCK_INTERNALS(internals) pycritical_section lock((internals).mutex)
#else
# define PYBIND11_LOCK_INTERNALS(internals)
#endif
@@ -912,7 +899,7 @@ inline auto with_exception_translators(const F &cb)
get_local_internals().registered_exception_translators)) {
auto &internals = get_internals();
#ifdef Py_GIL_DISABLED
std::unique_lock<pymutex> lock((internals).exception_translator_mutex);
pycritical_section lock((internals).exception_translator_mutex);
#endif
auto &local_internals = get_local_internals();
return cb(internals.registered_exception_translators,