Ocean
Loading...
Searching...
No Matches
Lock.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_BASE_LOCK_H
9#define META_OCEAN_BASE_LOCK_H
10
11#include "ocean/base/Base.h"
12
13#if defined(_WINDOWS)
14 #include <winsock2.h>
15 #include <windows.h>
16#else
17 #include <pthread.h>
18#endif
19
20namespace Ocean
21{
22
23/**
24 * This class implements a recursive lock object.
25 * You can either explicitly lock and unlock an Lock object by using the appropriated functions.<br>
26 * However, it's recommended to use the corresponding scope classes for this lock object.
27 * @see TemplatedLock, ScopedLock, TemplatedScopedLock, TemporaryScopedLock, OptionalScopedLock.
28 * @ingroup base
29 */
30class OCEAN_BASE_EXPORT Lock
31{
32 public:
33
34 /**
35 * Creates a new lock object.
36 */
37 inline Lock();
38
39 /**
40 * Destructs a lock object.
41 */
42 inline ~Lock();
43
44 /**
45 * Locks the critical section.
46 */
47 inline void lock();
48
49 /**
50 * Unlocks the critical section.
51 */
52 inline void unlock();
53
54 /**
55 * Returns whether this critical section is locked by another thread.
56 * @return True, if so
57 */
58 inline bool isLocked();
59
60 protected:
61
62 /**
63 * Disabled copy constructor.
64 * @param lock The lock object to be copied
65 */
66 Lock(const Lock& lock) = delete;
67
68 /**
69 * Disabled assign operator.
70 * @param lock The lock object to be assigned
71 * @return Reference to this object
72 */
73 Lock& operator=(const Lock& lock) = delete;
74
75 protected:
76
77#if defined(_WINDOWS)
78
79 /// Critical section object of windows.
80 CRITICAL_SECTION criticalSection_;
81
82#else
83
84 /// Pthread mutex object.
85 pthread_mutex_t mutex_;
86
87#endif
88
89};
90
91/**
92 * This class implements a template-based recursive lock object.
93 * The class allows to e.g., implement classes which can be thread-safe or not based on a template parameter.
94 * @tparam tActive True, to activate the lock; False, to avoid using the lock at all
95 * @ingroup base
96 */
97template <bool tActive>
98class TemplatedLock : public Lock
99{
100 // nothing to do here
101};
102
103/**
104 * Specialization of the TemplatedLock class.
105 * This class does nothing.
106 * @ingroup base
107 */
108template <>
109class TemplatedLock<false>
110{
111 protected:
112
113 /**
114 * Disabled copy constructor.
115 * @param lock The lock object to be copied
116 */
118
119 /**
120 * Disabled assign operator.
121 * @param lock The lock object to be assigned
122 * @return Reference to this object
123 */
125};
126
127/**
128 * This class implements a scoped lock object for recursive lock objects.
129 * The application of a scoped lock object ensures that a lock will be unlocked in any case if the scope (in which the object exists) ends.<br>
130 * Thus, possible dead locks can be avoided (e.g., if a function returns while the before the unlock() function of the Lock object is invoke or if an exception is thrown but not intercepted).
131 * @see Lock, TemplatedScopedLock, TemporaryScopedLock, OptionalScopedLock.
132 * @ingroup base
133 */
134class OCEAN_BASE_EXPORT ScopedLock
135{
136 public:
137
138 /**
139 * Creates a new scoped lock object by a given lock object.
140 * @param lock The lock object used for locking
141 */
142 explicit inline ScopedLock(Lock& lock);
143
144 /**
145 * Destructs a scoped lock and unlocks the internal lock object.
146 */
147 inline ~ScopedLock();
148
149 protected:
150
151 /**
152 * Disabled accessible copy operator.
153 * @param object The object to copy
154 */
155 ScopedLock(const ScopedLock& object) = delete;
156
157 /**
158 * Disabled accessible assigns operator.
159 * @param object The right object
160 * @return Reference to this object
161 */
162 ScopedLock& operator=(const ScopedLock& object) = delete;
163
164 protected:
165
166 /// Lock object which is locked during the existence of this scoped lock object.
168};
169
170/**
171 * This class implements a recursive scoped lock object that is activated by a boolean template parameter.
172 * @tparam tActive True, to active the scoped lock, false to deactivate the scoped lock
173 * @see Lock, ScopedLock, TemporaryScopedLock, OptionalScopedLock.
174 * @ingroup base
175 */
176template <bool tActive>
178{
179 public:
180
181 /**
182 * Creates a new scoped lock object by a given lock object.
183 * @param lock The lock object used for locking
184 */
185 explicit inline TemplatedScopedLock(Lock& lock);
186
187 /**
188 * Creates a new scoped lock object by a given lock object.
189 * @param lock The lock object used for locking
190 */
191 explicit inline TemplatedScopedLock(TemplatedLock<tActive>& lock);
192
193 /**
194 * Destructs a scoped lock and unlocks the internal lock object.
195 */
196 inline ~TemplatedScopedLock();
197
198 protected:
199
200 /**
201 * Disabled accessible copy operator.
202 * @param object The object to copy
203 */
205
206 /**
207 * Disabled accessible assigns operator.
208 * @param object The right object
209 * @return Reference to this object
210 */
212
213 protected:
214
215 /// Lock object which is locked during the existence of this scoped lock object.
217};
218
219/**
220 * Specialization of the TemplatedScopedLock class.
221 * This class does nothing.
222 * @ingroup base
223 */
224template <>
226{
227 public:
228
229 /**
230 * Creates a new scoped lock object by a given lock object.
231 * @param lock The lock object used for locking
232 */
233 explicit inline TemplatedScopedLock(Lock& lock)
234 {
235 OCEAN_SUPPRESS_UNUSED_WARNING(lock);
236 }
237
238 /**
239 * Creates a new scoped lock object by a given lock object.
240 * @param lock The lock object used for locking
241 */
243 {
244 OCEAN_SUPPRESS_UNUSED_WARNING(lock);
245 }
246};
247
248/**
249 * This class implements a recursive scoped lock object allowing to release the lock before the scoped object itself is released.
250 * @see Lock, ScopedLock, TemplatedScopedLock, OptionalScopedLock.
251 * @ingroup base
252 */
253class OCEAN_BASE_EXPORT TemporaryScopedLock
254{
255 public:
256
257 /**
258 * Creates a new scoped lock object which is not locked yet.
259 */
261
262 /**
263 * Creates a new scoped lock object by a given lock object.
264 * @param lock The lock object used for locking
265 */
266 explicit inline TemporaryScopedLock(Lock& lock);
267
268 /**
269 * Destructs a scoped lock and unlocks the internal lock object (if still locked).
270 */
271 inline ~TemporaryScopedLock();
272
273 /**
274 * Returns the lock object which (if existing) is locked during the existence of this scoped lock object.
275 * @return The associated lock object, nullptr if this object is already released (or was never locked)
276 */
277 [[nodiscard]] inline Lock* lock() const;
278
279 /**
280 * Explicitly releases the lock before the scoped lock object is released.
281 */
282 inline void release();
283
284 /**
285 * Re-locks this scoped lock with a given lock.
286 * This scoped lock must be released before re-locking it again.
287 * @param lock The lock to be used for locking
288 * @see isReleased().
289 */
290 inline void relock(Lock& lock);
291
292 /**
293 * Returns whether this scoped lock is released already.
294 * @return True, if so
295 */
296 inline bool isReleased() const;
297
298 protected:
299
300 /**
301 * Disabled accessible copy operator.
302 * @param object The object to copy
303 */
304 inline TemporaryScopedLock(const TemporaryScopedLock& object) = delete;
305
306 /**
307 * Disabled accessible assigns operator.
308 * @param object The right object
309 * @return Reference to this object
310 */
311 inline TemporaryScopedLock& operator=(const TemporaryScopedLock& object) = delete;
312
313 protected:
314
315 /// Lock object which is locked during the existence of this scoped lock object.
316 Lock* lock_ = nullptr;
317};
318
319/**
320 * This class implements an optional recursive scoped lock object locking the lock object only if it's defined.
321 * @see Lock, ScopedLock, TemplatedScopedLock, TemporaryScopedLock.
322 * @ingroup base
323 */
324class OCEAN_BASE_EXPORT OptionalScopedLock
325{
326 public:
327
328 /**
329 * Creates a new optional scoped lock object by a given lock object.
330 * @param lock Optional lock object used for locking, otherwise nullptr
331 */
332 explicit inline OptionalScopedLock(Lock* lock);
333
334 /**
335 * Creates a new optional scoped lock object by a given lock object and a boolean statement whether the lock is invoked or not.
336 * @param lock The lock object used for locking
337 * @param apply True, to invoke the lock; False, to avoid the locking
338 */
339 inline OptionalScopedLock(Lock& lock, const bool apply);
340
341 /**
342 * Destructs an optional scoped lock and unlocks the internal lock object if defined.
343 */
344 inline ~OptionalScopedLock();
345
346 /**
347 * Returns the lock object which (if existing) is locked during the existence of this scoped lock object.
348 * @return The associated lock object, nullptr if no lock object was provided when this object was created
349 */
350 [[nodiscard]] inline Lock* lock() const;
351
352 protected:
353
354 /**
355 * Disabled accessible copy operator.
356 * @param object The object to copy
357 */
358 inline OptionalScopedLock(const OptionalScopedLock& object) = delete;
359
360 /**
361 * Disabled accessible assigns operator.
362 * @param object The right object
363 * @return Reference to this object
364 */
365 inline OptionalScopedLock& operator=(const OptionalScopedLock& object) = delete;
366
367 protected:
368
369 /// Lock object which is locked during the existence of this scoped lock object.
370 Lock* lock_ = nullptr;
371};
372
374{
375#if defined(_WINDOWS)
376
377 InitializeCriticalSection(&criticalSection_);
378
379#elif defined(__APPLE__) || defined(__linux__) || defined(__EMSCRIPTEN__)
380
381 pthread_mutexattr_t mutexAttribute;
382 pthread_mutexattr_init(&mutexAttribute);
383 pthread_mutexattr_settype(&mutexAttribute, PTHREAD_MUTEX_RECURSIVE);
384 pthread_mutex_init(&mutex_, &mutexAttribute);
385
386#else
387
388 pthread_mutexattr_t mutexAttribute = PTHREAD_MUTEX_RECURSIVE;
389 pthread_mutex_init(&mutex_, &mutexAttribute);
390
391#endif
392
393}
394
396{
397
398#if defined(_WINDOWS)
399
400 ocean_assert(criticalSection_.RecursionCount == 0);
401 DeleteCriticalSection(&criticalSection_);
402
403#else
404
405 pthread_mutex_destroy(&mutex_);
406
407#endif
408
409}
410
411inline void Lock::lock()
412{
413#if defined(_WINDOWS)
414
415 EnterCriticalSection(&criticalSection_);
416
417#else
418
419 pthread_mutex_lock(&mutex_);
420
421#endif
422
423}
424
425inline void Lock::unlock()
426{
427
428#if defined(_WINDOWS)
429
430 LeaveCriticalSection(&criticalSection_);
431
432#else
433
434 pthread_mutex_unlock(&mutex_);
435
436#endif
437
438}
439
440inline bool Lock::isLocked()
441{
442#if defined(_WINDOWS)
443
444 if (TryEnterCriticalSection(&criticalSection_) == TRUE)
445 {
446 LeaveCriticalSection(&criticalSection_);
447 return false;
448 }
449
450#else
451
452 if (pthread_mutex_trylock(&mutex_) == 0)
453 {
454 pthread_mutex_unlock(&mutex_);
455 return false;
456 }
457
458#endif
459
460 return true;
461}
462
464 lock_(lock)
465{
466 lock_.lock();
467}
468
470{
471 lock_.unlock();
472}
473
474template <bool tActive>
476 lock_(lock)
477{
478 lock_.lock();
479}
480
481template <bool tActive>
483 lock_(lock)
484{
485 lock.lock();
486}
487
488template <bool tActive>
490{
491 lock_.unlock();
492}
493
495 lock_(&lock)
496{
497 ocean_assert(lock_ != nullptr);
498 lock_->lock();
499}
500
502{
503 if (lock_ != nullptr)
504 {
505 lock_->unlock();
506 }
507}
508
510{
511 return lock_;
512}
513
515{
516 ocean_assert(!isReleased() && "This TemporaryScopedLock object has been released before");
517
518 if (lock_ != nullptr)
519 {
520 lock_->unlock();
521 lock_ = nullptr;
522 }
523}
524
526{
527 ocean_assert(isReleased() && "This TemporaryScopedLock object must be released before");
528
529 if (lock_ == nullptr)
530 {
531 lock_ = &lock;
532 lock_->lock();
533 }
534}
535
537{
538 return lock_ == nullptr;
539}
540
542 lock_(lock)
543{
544 if (lock_ != nullptr)
545 {
546 lock_->lock();
547 }
548}
549
550inline OptionalScopedLock::OptionalScopedLock(Lock& lock, const bool apply) :
551 lock_(nullptr)
552{
553 if (apply)
554 {
555 lock_ = &lock;
556 lock_->lock();
557 }
558}
559
561{
562 if (lock_ != nullptr)
563 {
564 lock_->unlock();
565 }
566}
567
569{
570 return lock_;
571}
572
573}
574
575#endif // META_OCEAN_BASE_LOCK_H
This class implements a recursive lock object.
Definition Lock.h:31
CRITICAL_SECTION criticalSection_
Critical section object of windows.
Definition Lock.h:80
void lock()
Locks the critical section.
Definition Lock.h:411
~Lock()
Destructs a lock object.
Definition Lock.h:395
bool isLocked()
Returns whether this critical section is locked by another thread.
Definition Lock.h:440
Lock & operator=(const Lock &lock)=delete
Disabled assign operator.
void unlock()
Unlocks the critical section.
Definition Lock.h:425
Lock(const Lock &lock)=delete
Disabled copy constructor.
Lock()
Creates a new lock object.
Definition Lock.h:373
pthread_mutex_t mutex_
Pthread mutex object.
Definition Lock.h:85
This class implements an optional recursive scoped lock object locking the lock object only if it's d...
Definition Lock.h:325
~OptionalScopedLock()
Destructs an optional scoped lock and unlocks the internal lock object if defined.
Definition Lock.h:560
Lock * lock() const
Returns the lock object which (if existing) is locked during the existence of this scoped lock object...
Definition Lock.h:568
OptionalScopedLock & operator=(const OptionalScopedLock &object)=delete
Disabled accessible assigns operator.
Lock * lock_
Lock object which is locked during the existence of this scoped lock object.
Definition Lock.h:370
OptionalScopedLock(Lock *lock)
Creates a new optional scoped lock object by a given lock object.
Definition Lock.h:541
OptionalScopedLock(const OptionalScopedLock &object)=delete
Disabled accessible copy operator.
This class implements a scoped lock object for recursive lock objects.
Definition Lock.h:135
~ScopedLock()
Destructs a scoped lock and unlocks the internal lock object.
Definition Lock.h:469
ScopedLock(const ScopedLock &object)=delete
Disabled accessible copy operator.
ScopedLock & operator=(const ScopedLock &object)=delete
Disabled accessible assigns operator.
ScopedLock(Lock &lock)
Creates a new scoped lock object by a given lock object.
Definition Lock.h:463
Lock & lock_
Lock object which is locked during the existence of this scoped lock object.
Definition Lock.h:167
TemplatedLock & operator=(const TemplatedLock &lock)=delete
Disabled assign operator.
TemplatedLock(const TemplatedLock &lock)=delete
Disabled copy constructor.
This class implements a template-based recursive lock object.
Definition Lock.h:99
TemplatedScopedLock(Lock &lock)
Creates a new scoped lock object by a given lock object.
Definition Lock.h:233
TemplatedScopedLock(TemplatedLock< false > &lock)
Creates a new scoped lock object by a given lock object.
Definition Lock.h:242
This class implements a recursive scoped lock object that is activated by a boolean template paramete...
Definition Lock.h:178
TemplatedScopedLock(Lock &lock)
Creates a new scoped lock object by a given lock object.
Definition Lock.h:475
TemplatedScopedLock & operator=(const TemplatedScopedLock< tActive > &object)=delete
Disabled accessible assigns operator.
TemplatedScopedLock(const TemplatedScopedLock< tActive > &object)=delete
Disabled accessible copy operator.
~TemplatedScopedLock()
Destructs a scoped lock and unlocks the internal lock object.
Definition Lock.h:489
Lock & lock_
Lock object which is locked during the existence of this scoped lock object.
Definition Lock.h:216
This class implements a recursive scoped lock object allowing to release the lock before the scoped o...
Definition Lock.h:254
void relock(Lock &lock)
Re-locks this scoped lock with a given lock.
Definition Lock.h:525
TemporaryScopedLock(const TemporaryScopedLock &object)=delete
Disabled accessible copy operator.
Lock * lock() const
Returns the lock object which (if existing) is locked during the existence of this scoped lock object...
Definition Lock.h:509
void release()
Explicitly releases the lock before the scoped lock object is released.
Definition Lock.h:514
TemporaryScopedLock()=default
Creates a new scoped lock object which is not locked yet.
Lock * lock_
Lock object which is locked during the existence of this scoped lock object.
Definition Lock.h:316
TemporaryScopedLock & operator=(const TemporaryScopedLock &object)=delete
Disabled accessible assigns operator.
bool isReleased() const
Returns whether this scoped lock is released already.
Definition Lock.h:536
~TemporaryScopedLock()
Destructs a scoped lock and unlocks the internal lock object (if still locked).
Definition Lock.h:501
The namespace covering the entire Ocean framework.
Definition Accessor.h:15