1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
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 "<shared_mutex>" 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 <typename... LockTs>
void __pyx_py_safe_std_lock(LockTs& ...locks);
template <typename MutexT>
std::shared_lock<MutexT> __pyx_py_safe_construct_shared_lock(MutexT &m) {
std::shared_lock<MutexT> 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
|