from libcpp cimport bool from libcpp.mutex cimport defer_lock_t, defer_lock, try_to_lock_t, try_to_lock, adopt_lock_t, adopt_lock cdef extern from "" namespace "std" nogil: cppclass shared_mutex: # may not be present, and we know nothing about it cppclass native_handle_type: pass # We strongly recommend not calling lock with the GIL held (to avoid deadlocks) void lock() except+ bool try_lock() void unlock() # We strongly recommend not calling lock_shared with the GIL held (to avoid deadlocks) void lock_shared() except+ bool try_lock_shared() void unlock_shared() native_handle_type native_handle() except+ cppclass shared_timed_mutex: # may not be present, and we know nothing about it. # For shared_timed_mutex cppreference doesn't mention this cppclass native_handle_type: pass # We strongly recommend not calling lock with the GIL held (to avoid deadlocks) # and moderately recommend not calling the timed lock functions with the GIL either. void lock() except+ bool try_lock() bool try_lock_for[T](const T& duration) except+ bool try_lock_until[T](const T& time_point) except+ void unlock() # We strongly recommend not calling lock_shared with the GIL held (to avoid deadlocks) # and moderately recommend not calling the timed lock functions with the GIL either. void lock_shared() except+ bool try_lock_shared() bool try_lock_shared_for[T](const T& duration) except+ bool try_lock_shared_until[T](const T& time_point) except+ void unlock_shared() native_handle_type native_handle() except+ # We strongly recommend not attempting to acquire a lock via a shared_lock while holding # the GIL. Use py_safe_construct_shared_lock instead. cppclass shared_lock[T]: ctypedef T mutex_type # This covers both the plain regular constructor, the 3 versions with tags # and two std::chrono constructors. The two templated chrono versions stop # us from declaring the overloads explicitly. shared_lock() shared_lock(mutex_type&, ...) except+ #shared_lock(mutex_type&, defer_lock_t) #shared_lock(mutex_type&, try_to_lock_t) except+ ## this feels like it should be noexcept, but cppreference implies it isn't #shared_lock(mutex_type&, adopt_lock_t) except+ # We strongly recommend not calling lock with the GIL held (to avoid deadlocks) void lock() except+ bool try_lock() except+ bool try_lock_for[T](const T& duration) except+ bool try_lock_until[T](const T& time_point) except+ void unlock() except+ # We strongly recommend not calling lock_shared with the GIL held (to avoid deadlocks) void swap(shared_lock& other) # "release" is definitely not the same as unlock. Noted here because # DW always makes this mistake and regrets it and wants to save you # from the same fate. mutex_type* release() mutex_type* mutex() bool owns_lock() bool operator bool() # Just to get our GIL-safe utility code cimport libcpp.mutex as _cpp_mutex cdef extern from *: """ namespace { template void __pyx_py_safe_std_lock(LockTs& ...locks); template std::shared_lock __pyx_py_safe_construct_shared_lock(MutexT &m) { std::shared_lock l(m, std::defer_lock); __pyx_py_safe_std_lock(l); // in mutex.pxd return l; } } """ # Construct a shared_lock while holding the GIL, without deadlock on the GIL shared_lock[MutexT] py_safe_construct_shared_lock "__pyx_py_safe_construct_shared_lock" [MutexT](MutexT& m) except+ nogil