MySQL 8.3.0
Source Code Documentation
shared_spin_lock.h
Go to the documentation of this file.
1/* Copyright (c) 2020, 2023, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23#ifndef LOCK_SHARED_SPIN_LOCK_INCLUDED
24#define LOCK_SHARED_SPIN_LOCK_INCLUDED
25
26#include <atomic>
27#include <map>
28#include <memory>
29#include <type_traits>
30
32
33/**
34 Provides atomic access in shared-exclusive modes. Shared mode allows for
35 several threads to share lock acquisition. Exclusive mode will allow for
36 a single thread to acquire the lock.
37
38 The implementation also provides re-entrance, meaning that a thread is
39 allowed to acquire the lock in the same mode several times without
40 blocking. Re-entrance is symmetric, meaning, in the case the lock is
41 acquired several times by the same thread, it should be released the same
42 amount of times.
43
44 Acquisition request priority management is implemented to avoid
45 starvation, meaning:
46
47 1) When no thread is holding the lock, acquisition is granted to the
48 first thread to request it.
49
50 2) If the lock is being held in shared mode and an exclusive acquisition
51 request is made, no more shared or exclusive acquisition requests are
52 granted until the exclusivity request is granted and released.
53
54 The acquisition relation given to concurrent requests is as follows:
55
56 -------------------------------------------------------------
57 | S2 | E2 |
58 +-----------------------------+-----------------------------+
59 | REQUEST | ACQUIRED | REQUEST | ACQUIRED |
60 -----------------+--------------+--------------------------------------------+
61 | | REQUEST | S1 & S2 | S1 & S2 | S1 | E2 | E2 |
62 | S1 |---------+--------------+--------------+--------------+--------------+
63 | | ACQUIRED| S1 & S2 | S1 & S2 | S1 | - |
64 -------+---------+--------------+--------------+--------------+--------------+
65 | | REQUEST | E1 | S2 | E1 | E2 | E2 |
66 | E1 |---------+--------------+--------------+--------------+--------------+
67 | | ACQUIRED| E1 | - | E1 | - |
68 ------------------------------------------------------------------------------
69
70 Legend:
71 - S1: Thread that is requesting or has acquired in shared mode
72 - S2: Thread that is requesting or has acquired in shared mode
73 - E1: Thread that is requesting or has acquired in exclusive mode
74 - E2: Thread that is requesting or has acquired in exclusive mode
75
76
77 */
78namespace lock {
80 public:
82 SL_EXCLUSIVE = 0,
83 SL_SHARED = 1,
85 };
86
87 /**
88 Sentry class for `Shared_spin_lock` to deliver RAII pattern usability.
89 */
90 class Guard {
91 public:
92 friend class Shared_spin_lock;
93
94 /**
95 Class constructor that receives the target spin-lock, whether or not
96 it can be a shared acquisition and whether or not it should be a
97 try-and-fail lock attempt, instead of a blocking attempt.
98
99 @param target The target spin-lock.
100 @param acquisition the acquisition type, SHARED, EXCLUSIVE or
101 NO_ACQUISITION
102 @param try_and_fail whether or not the lock attempt should be
103 blocking (only used if acquisition type is SHARED
104 or EXCLUSIVE).
105 */
106 Guard(Shared_spin_lock &target,
108 bool try_and_fail = false);
109 // Delete copy and move constructors
112 //
113 /**
114 Destructor for the sentry. It will release any acquisition, shared or
115 exclusive.
116 */
117 virtual ~Guard();
118
119 // Delete copy and move operators
121 delete;
123 //
124
125 /**
126 Arrow operator to access the underlying lock.
127
128 @return A pointer to the underlying lock.
129 */
131 /**
132 Star operator to access the underlying lock.
133
134 @return A reference to the underlying lock.
135 */
137 /**
138 If this instance was initialized without acquiring the lock
139 (`NO_ACQUISITION ` passed to constructor) or the acquisition request
140 wasn't granted (passing `try_and_fail = true` to the constructor),
141 invoking this method will try to acquire the lock in the provided
142 mode.
143
144 @param acquisition the acquisition type, SHARED or EXCLUSIVE
145 @param try_and_fail whether or not the lock attempt should be
146 blocking
147
148 @return A reference to `this` object, for chaining purposes.
149 */
151 bool try_and_fail = false);
152 /**
153 Releases the underlying lock acquisition, if any.
154
155 @return A reference to `this` object, for chaining purposes.
156 */
158
159 private:
160 /** The underlying lock */
162 /** The type of lock acquisition to be requested */
164 };
166
167 /**
168 Default class constructor.
169 */
170 Shared_spin_lock() = default;
171 /**
172 Default class destructor.
173 */
174 virtual ~Shared_spin_lock() = default;
175
176 /**
177 Blocks until the lock is acquired in shared mode.
178
179 @return A reference to `this` object, for chaining purposes.
180 */
182 /**
183 Blocks until the lock is acquired in exclusive mode.
184
185 @return A reference to `this` object, for chaining purposes.
186 */
188 /**
189 Tries to acquire the lock in shared mode.
190
191 @return A reference to `this` object, for chaining purposes.
192 */
194 /**
195 Tries to acquire the lock in exclusive mode.
196
197 @return A reference to `this` object, for chaining purposes.
198 */
200 /**
201 Releases the previously granted shared acquisition request.
202
203 @return A reference to `this` object, for chaining purposes.
204 */
206 /**
207 Releases the previously granted exclusive acquisition request.
208
209 @return A reference to `this` object, for chaining purposes.
210 */
212 /**
213 Returns whether the lock is acquired for shared access by the invoking
214 thread.
215
216 @return true if the lock was acquired in shared mode by the invoking
217 thread
218 */
220 /**
221 Returns whether the lock is acquired for exclusive access by the
222 invoking thread.
223
224 @return true if the lock was acquired in exclusive mode by the invoking
225 thread
226 */
228
229 private:
230 /** The total amount of threads accessing in shared mode */
232 /** Whether or not any thread is accessing in or waiting for exclusive mode */
234
235 /**
236 Tries to lock or waits for locking in shared mode and increases the
237 thread-local lock acquisition shared counter.
238
239 @param try_and_fail Whether or not to try to lock of wait for acquiring.
240
241 @return A reference to `this` object, for chaining purposes.
242 */
243 Shared_spin_lock &try_or_spin_shared_lock(bool try_and_fail);
244 /**
245 Tries to lock or waits for locking in shared mode and increases the
246 thread-local lock acquisition shared counter.
247
248 @param try_and_fail Whether or not to try to lock of wait for acquiring.
249
250 @return A reference to `this` object, for chaining purposes.
251 */
253 /**
254 Tries to acquire in shared mode.
255
256 @return `true` if the attempt to acquire the lock in shared mode was
257 successful.
258 */
259 bool try_shared_lock();
260 /**
261 Tries to acquire in exclusive mode.
262
263 @return `true` if the attempt to acquire the lock in exclusive mode was
264 successful.
265 */
266 bool try_exclusive_lock();
267 /**
268 Blocks until the lock is acquired in shared mode.
269 */
270 void spin_shared_lock();
271 /**
272 Blocks until the lock is acquired in exclusive mode.
273 */
274 void spin_exclusive_lock();
275 /**
276 Returns the thread-local lock counter map.
277 */
278 static std::map<Shared_spin_lock *, long> &acquired_spins();
279};
280} // namespace lock
281
282#endif // LOCK_SHARED_SPIN_LOCK_INCLUDED
Sentry class for Shared_spin_lock to deliver RAII pattern usability.
Definition: shared_spin_lock.h:90
Shared_spin_lock & operator*()
Star operator to access the underlying lock.
Definition: shared_spin_lock.cc:49
Guard(Shared_spin_lock &target, enum_lock_acquisition acquisition=enum_lock_acquisition::SL_SHARED, bool try_and_fail=false)
Class constructor that receives the target spin-lock, whether or not it can be a shared acquisition a...
Definition: shared_spin_lock.cc:32
Shared_spin_lock * operator->()
Arrow operator to access the underlying lock.
Definition: shared_spin_lock.cc:45
Shared_spin_lock::Guard & release()
Releases the underlying lock acquisition, if any.
Definition: shared_spin_lock.cc:90
virtual ~Guard()
Destructor for the sentry.
Definition: shared_spin_lock.cc:43
Guard(Shared_spin_lock::Guard const &)=delete
Shared_spin_lock::Guard & operator=(Shared_spin_lock::Guard const &)=delete
Guard(Shared_spin_lock::Guard &&)=delete
Shared_spin_lock::Guard & operator=(Shared_spin_lock::Guard &&)=delete
enum_lock_acquisition m_acquisition
The type of lock acquisition to be requested.
Definition: shared_spin_lock.h:163
Shared_spin_lock::Guard & acquire(enum_lock_acquisition acquisition, bool try_and_fail=false)
If this instance was initialized without acquiring the lock (NO_ACQUISITION passed to constructor) or...
Definition: shared_spin_lock.cc:53
Shared_spin_lock & m_target
The underlying lock.
Definition: shared_spin_lock.h:161
Definition: shared_spin_lock.h:79
memory::Aligned_atomic< bool > m_exclusive_access
Whether or not any thread is accessing in or waiting for exclusive mode.
Definition: shared_spin_lock.h:233
void spin_shared_lock()
Blocks until the lock is acquired in shared mode.
Definition: shared_spin_lock.cc:232
Shared_spin_lock & try_exclusive()
Tries to acquire the lock in exclusive mode.
Definition: shared_spin_lock.cc:123
enum_lock_acquisition
Definition: shared_spin_lock.h:81
Shared_spin_lock()=default
Default class constructor.
bool try_shared_lock()
Tries to acquire in shared mode.
Definition: shared_spin_lock.cc:207
void spin_exclusive_lock()
Blocks until the lock is acquired in exclusive mode.
Definition: shared_spin_lock.cc:251
bool is_shared_acquisition()
Returns whether the lock is acquired for shared access by the invoking thread.
Definition: shared_spin_lock.cc:157
Shared_spin_lock & try_or_spin_shared_lock(bool try_and_fail)
Tries to lock or waits for locking in shared mode and increases the thread-local lock acquisition sha...
Definition: shared_spin_lock.cc:169
static std::map< Shared_spin_lock *, long > & acquired_spins()
Returns the thread-local lock counter map.
Definition: shared_spin_lock.cc:261
bool try_exclusive_lock()
Tries to acquire in exclusive mode.
Definition: shared_spin_lock.cc:221
Shared_spin_lock & try_shared()
Tries to acquire the lock in shared mode.
Definition: shared_spin_lock.cc:119
Shared_spin_lock & try_or_spin_exclusive_lock(bool try_and_fail)
Tries to lock or waits for locking in shared mode and increases the thread-local lock acquisition sha...
Definition: shared_spin_lock.cc:188
Shared_spin_lock & release_shared()
Releases the previously granted shared acquisition request.
Definition: shared_spin_lock.cc:127
Shared_spin_lock & acquire_shared()
Blocks until the lock is acquired in shared mode.
Definition: shared_spin_lock.cc:111
memory::Aligned_atomic< long > m_shared_access
The total amount of threads accessing in shared mode
Definition: shared_spin_lock.h:231
Shared_spin_lock & release_exclusive()
Releases the previously granted exclusive acquisition request.
Definition: shared_spin_lock.cc:142
virtual ~Shared_spin_lock()=default
Default class destructor.
Shared_spin_lock & acquire_exclusive()
Blocks until the lock is acquired in exclusive mode.
Definition: shared_spin_lock.cc:115
bool is_exclusive_acquisition()
Returns whether the lock is acquired for exclusive access by the invoking thread.
Definition: shared_spin_lock.cc:163
Templated class that encapsulates an std::atomic within a byte buffer that is padded to the processor...
Definition: aligned_atomic.h:157
Provides atomic access in shared-exclusive modes.
Definition: shared_spin_lock.h:78