MySQL  8.0.27
Source Code Documentation
shared_spin_lock.h
Go to the documentation of this file.
1 /* Copyright (c) 2020, 2021, 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. Reentrance is symetric, 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  */
78 namespace lock {
80  public:
81  enum class enum_lock_acquisition {
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
110  Guard(Shared_spin_lock::Guard const &) = delete;
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 refernce 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  */
219  bool is_shared_acquisition();
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  */
252  Shared_spin_lock &try_or_spin_exclusive_lock(bool try_and_fail);
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
Shared_spin_lock::Guard & operator=(Shared_spin_lock::Guard &&)=delete
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
Shared_spin_lock::Guard & operator=(Shared_spin_lock::Guard const &)=delete
Guard(Shared_spin_lock::Guard const &)=delete
Guard(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
Provides atomic access in shared-exclusive modes.
Definition: shared_spin_lock.h:78