1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
7 #include "common/containers.h"
12 // For general code making use of mutexes, use these ceph:: types.
13 // The key requirement is that you make use of the ceph::make_mutex()
14 // and make_recursive_mutex() factory methods, which take a string
15 // naming the mutex for the purposes of the lockdep debug variant.
17 #if defined(WITH_SEASTAR) && !defined(WITH_ALIEN)
20 // an empty class satisfying the mutex concept
28 void unlock_shared() {}
31 struct dummy_shared_mutex
: dummy_mutex
{
33 void unlock_shared() {}
36 using mutex
= dummy_mutex
;
37 using recursive_mutex
= dummy_mutex
;
38 using shared_mutex
= dummy_shared_mutex
;
39 // in seastar, we should use a difference interface for enforcing the
40 // semantics of condition_variable
42 template <typename
...Args
>
43 dummy_mutex
make_mutex(Args
&& ...args
) {
47 template <typename
...Args
>
48 recursive_mutex
make_recursive_mutex(Args
&& ...args
) {
52 template <typename
...Args
>
53 shared_mutex
make_shared_mutex(Args
&& ...args
) {
57 #define ceph_mutex_is_locked(m) true
58 #define ceph_mutex_is_locked_by_me(m) true
61 #else // defined (WITH_SEASTAR) && !defined(WITH_ALIEN)
63 // For legacy Mutex users that passed recursive=true, use
64 // ceph::make_recursive_mutex. For legacy Mutex users that passed
65 // lockdep=false, use std::mutex directly.
67 #ifdef CEPH_DEBUG_MUTEX
69 // ============================================================================
70 // debug (lockdep-capable, various sanity checks and asserts)
71 // ============================================================================
73 // Note: this is known to cause deadlocks on Windows because
74 // of the winpthreads shared mutex implementation.
76 #include "common/condition_variable_debug.h"
77 #include "common/mutex_debug.h"
78 #include "common/shared_mutex_debug.h"
81 typedef ceph::mutex_debug mutex
;
82 typedef ceph::mutex_recursive_debug recursive_mutex
;
83 typedef ceph::condition_variable_debug condition_variable
;
84 typedef ceph::shared_mutex_debug shared_mutex
;
86 // pass arguments to mutex_debug ctor
87 template <typename
...Args
>
88 mutex
make_mutex(Args
&& ...args
) {
89 return {std::forward
<Args
>(args
)...};
92 // pass arguments to recursive_mutex_debug ctor
93 template <typename
...Args
>
94 recursive_mutex
make_recursive_mutex(Args
&& ...args
) {
95 return {std::forward
<Args
>(args
)...};
98 // pass arguments to shared_mutex_debug ctor
99 template <typename
...Args
>
100 shared_mutex
make_shared_mutex(Args
&& ...args
) {
101 return {std::forward
<Args
>(args
)...};
105 #define ceph_mutex_is_locked(m) ((m).is_locked())
106 #define ceph_mutex_is_not_locked(m) (!(m).is_locked())
107 #define ceph_mutex_is_rlocked(m) ((m).is_rlocked())
108 #define ceph_mutex_is_wlocked(m) ((m).is_wlocked())
109 #define ceph_mutex_is_locked_by_me(m) ((m).is_locked_by_me())
110 #define ceph_mutex_is_not_locked_by_me(m) (!(m).is_locked_by_me())
115 // ============================================================================
116 // release (fast and minimal)
117 // ============================================================================
119 #include <condition_variable>
122 // The winpthreads shared mutex implementation is broken.
123 // We'll use boost::shared_mutex instead.
124 // https://github.com/msys2/MINGW-packages/issues/3319
126 #include <boost/thread/shared_mutex.hpp>
128 #include <shared_mutex>
133 typedef std::mutex mutex
;
134 typedef std::recursive_mutex recursive_mutex
;
135 typedef std::condition_variable condition_variable
;
138 typedef boost::shared_mutex shared_mutex
;
140 typedef std::shared_mutex shared_mutex
;
143 // discard arguments to make_mutex (they are for debugging only)
144 template <typename
...Args
>
145 mutex
make_mutex(Args
&& ...args
) {
148 template <typename
...Args
>
149 recursive_mutex
make_recursive_mutex(Args
&& ...args
) {
152 template <typename
...Args
>
153 shared_mutex
make_shared_mutex(Args
&& ...args
) {
157 // debug methods. Note that these can blindly return true
158 // because any code that does anything other than assert these
159 // are true is broken.
160 #define ceph_mutex_is_locked(m) true
161 #define ceph_mutex_is_not_locked(m) true
162 #define ceph_mutex_is_rlocked(m) true
163 #define ceph_mutex_is_wlocked(m) true
164 #define ceph_mutex_is_locked_by_me(m) true
165 #define ceph_mutex_is_not_locked_by_me(m) true
169 #endif // CEPH_DEBUG_MUTEX
171 #endif // WITH_SEASTAR
175 template <class LockT
,
177 ceph::containers::tiny_vector
<LockT
> make_lock_container(
178 const std::size_t num_instances
,
179 LockFactoryT
&& lock_factory
)
182 num_instances
, [&](const std::size_t i
, auto emplacer
) {
183 // this will be called `num_instances` times
184 new (emplacer
.data()) LockT
{lock_factory(i
)};