]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/ceph_mutex.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / common / ceph_mutex.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #pragma once
5
6 #include <utility>
7 #include "common/containers.h"
8
9 // What and why
10 // ============
11 //
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.
16
17 #if defined(WITH_SEASTAR) && !defined(WITH_ALIEN)
18
19 namespace ceph {
20 // an empty class satisfying the mutex concept
21 struct dummy_mutex {
22 void lock() {}
23 bool try_lock() {
24 return true;
25 }
26 void unlock() {}
27 void lock_shared() {}
28 void unlock_shared() {}
29 };
30
31 struct dummy_shared_mutex : dummy_mutex {
32 void lock_shared() {}
33 void unlock_shared() {}
34 };
35
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
41
42 template <typename ...Args>
43 dummy_mutex make_mutex(Args&& ...args) {
44 return {};
45 }
46
47 template <typename ...Args>
48 recursive_mutex make_recursive_mutex(Args&& ...args) {
49 return {};
50 }
51
52 template <typename ...Args>
53 shared_mutex make_shared_mutex(Args&& ...args) {
54 return {};
55 }
56
57 #define ceph_mutex_is_locked(m) true
58 #define ceph_mutex_is_locked_by_me(m) true
59 }
60
61 #else // defined (WITH_SEASTAR) && !defined(WITH_ALIEN)
62 //
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.
66
67 #ifdef CEPH_DEBUG_MUTEX
68
69 // ============================================================================
70 // debug (lockdep-capable, various sanity checks and asserts)
71 // ============================================================================
72
73 #include "common/condition_variable_debug.h"
74 #include "common/mutex_debug.h"
75 #include "common/shared_mutex_debug.h"
76
77 namespace ceph {
78 typedef ceph::mutex_debug mutex;
79 typedef ceph::mutex_recursive_debug recursive_mutex;
80 typedef ceph::condition_variable_debug condition_variable;
81 typedef ceph::shared_mutex_debug shared_mutex;
82
83 // pass arguments to mutex_debug ctor
84 template <typename ...Args>
85 mutex make_mutex(Args&& ...args) {
86 return {std::forward<Args>(args)...};
87 }
88
89 // pass arguments to recursive_mutex_debug ctor
90 template <typename ...Args>
91 recursive_mutex make_recursive_mutex(Args&& ...args) {
92 return {std::forward<Args>(args)...};
93 }
94
95 // pass arguments to shared_mutex_debug ctor
96 template <typename ...Args>
97 shared_mutex make_shared_mutex(Args&& ...args) {
98 return {std::forward<Args>(args)...};
99 }
100
101 // debug methods
102 #define ceph_mutex_is_locked(m) ((m).is_locked())
103 #define ceph_mutex_is_not_locked(m) (!(m).is_locked())
104 #define ceph_mutex_is_rlocked(m) ((m).is_rlocked())
105 #define ceph_mutex_is_wlocked(m) ((m).is_wlocked())
106 #define ceph_mutex_is_locked_by_me(m) ((m).is_locked_by_me())
107 #define ceph_mutex_is_not_locked_by_me(m) (!(m).is_locked_by_me())
108 }
109
110 #else
111
112 // ============================================================================
113 // release (fast and minimal)
114 // ============================================================================
115
116 #include <condition_variable>
117 #include <mutex>
118 #include <shared_mutex>
119
120
121 namespace ceph {
122
123 typedef std::mutex mutex;
124 typedef std::recursive_mutex recursive_mutex;
125 typedef std::condition_variable condition_variable;
126 typedef std::shared_mutex shared_mutex;
127
128 // discard arguments to make_mutex (they are for debugging only)
129 template <typename ...Args>
130 std::mutex make_mutex(Args&& ...args) {
131 return {};
132 }
133 template <typename ...Args>
134 std::recursive_mutex make_recursive_mutex(Args&& ...args) {
135 return {};
136 }
137 template <typename ...Args>
138 std::shared_mutex make_shared_mutex(Args&& ...args) {
139 return {};
140 }
141
142 // debug methods. Note that these can blindly return true
143 // because any code that does anything other than assert these
144 // are true is broken.
145 #define ceph_mutex_is_locked(m) true
146 #define ceph_mutex_is_not_locked(m) true
147 #define ceph_mutex_is_rlocked(m) true
148 #define ceph_mutex_is_wlocked(m) true
149 #define ceph_mutex_is_locked_by_me(m) true
150 #define ceph_mutex_is_not_locked_by_me(m) true
151
152 }
153
154 #endif // CEPH_DEBUG_MUTEX
155
156 #endif // WITH_SEASTAR
157
158 namespace ceph {
159
160 template <class LockT,
161 class LockFactoryT>
162 ceph::containers::tiny_vector<LockT> make_lock_container(
163 const std::size_t num_instances,
164 LockFactoryT&& lock_factory)
165 {
166 return {
167 num_instances, [&](const std::size_t i, auto emplacer) {
168 // this will be called `num_instances` times
169 new (emplacer.data()) LockT {lock_factory(i)};
170 }
171 };
172 }
173 } // namespace ceph
174