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