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 public:
101
102 /**
103 * Creates a new lock object.
104 */
105 TemplatedLock() = default;
106};
107
108/**
109 * Specialization of the TemplatedLock class.
110 * This class does nothing.
111 * @ingroup base
112 */
113template <>
114class TemplatedLock<false>
115{
116 public:
117
118 /**
119 * Creates a new lock object.
120 */
121 TemplatedLock() = default;
122
123 protected:
124
125 /**
126 * Disabled copy constructor.
127 * @param lock The lock object to be copied
128 */
130
131 /**
132 * Disabled assign operator.
133 * @param lock The lock object to be assigned
134 * @return Reference to this object
135 */
137};
138
139/**
140 * This class implements a scoped lock object for recursive lock objects.
141 * 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>
142 * 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).
143 * @see Lock, TemplatedScopedLock, TemporaryScopedLock, OptionalScopedLock.
144 * @ingroup base
145 */
146class OCEAN_BASE_EXPORT ScopedLock
147{
148 public:
149
150 /**
151 * Creates a new scoped lock object by a given lock object.
152 * @param lock The lock object used for locking
153 */
154 explicit inline ScopedLock(Lock& lock);
155
156 /**
157 * Destructs a scoped lock and unlocks the internal lock object.
158 */
159 inline ~ScopedLock();
160
161 protected:
162
163 /**
164 * Disabled accessible copy operator.
165 * @param object The object to copy
166 */
167 ScopedLock(const ScopedLock& object) = delete;
168
169 /**
170 * Disabled accessible assigns operator.
171 * @param object The right object
172 * @return Reference to this object
173 */
174 ScopedLock& operator=(const ScopedLock& object) = delete;
175
176 protected:
177
178 /// Lock object which is locked during the existence of this scoped lock object.
180};
181
182/**
183 * This class implements a recursive scoped lock object that is activated by a boolean template parameter.
184 * @tparam tActive True, to active the scoped lock, false to deactivate the scoped lock
185 * @see Lock, ScopedLock, TemporaryScopedLock, OptionalScopedLock.
186 * @ingroup base
187 */
188template <bool tActive>
190{
191 public:
192
193 /**
194 * Creates a new scoped lock object by a given lock object.
195 * @param lock The lock object used for locking
196 */
197 explicit inline TemplatedScopedLock(Lock& lock);
198
199 /**
200 * Creates a new scoped lock object by a given lock object.
201 * @param lock The lock object used for locking
202 */
203 explicit inline TemplatedScopedLock(TemplatedLock<tActive>& lock);
204
205 /**
206 * Destructs a scoped lock and unlocks the internal lock object.
207 */
208 inline ~TemplatedScopedLock();
209
210 protected:
211
212 /**
213 * Disabled accessible copy operator.
214 * @param object The object to copy
215 */
217
218 /**
219 * Disabled accessible assigns operator.
220 * @param object The right object
221 * @return Reference to this object
222 */
224
225 protected:
226
227 /// Lock object which is locked during the existence of this scoped lock object.
229};
230
231/**
232 * Specialization of the TemplatedScopedLock class.
233 * This class does nothing.
234 * @ingroup base
235 */
236template <>
238{
239 public:
240
241 /**
242 * Creates a new scoped lock object by a given lock object.
243 * @param lock The lock object used for locking
244 */
245 explicit inline TemplatedScopedLock(Lock& lock)
246 {
247 OCEAN_SUPPRESS_UNUSED_WARNING(lock);
248 }
249
250 /**
251 * Creates a new scoped lock object by a given lock object.
252 * @param lock The lock object used for locking
253 */
255 {
256 OCEAN_SUPPRESS_UNUSED_WARNING(lock);
257 }
258};
259
260/**
261 * This class implements a recursive scoped lock object allowing to release the lock before the scoped object itself is released.
262 * @see Lock, ScopedLock, TemplatedScopedLock, OptionalScopedLock.
263 * @ingroup base
264 */
265class OCEAN_BASE_EXPORT TemporaryScopedLock
266{
267 public:
268
269 /**
270 * Creates a new scoped lock object which is not locked yet.
271 */
273
274 /**
275 * Creates a new scoped lock object by a given lock object.
276 * @param lock The lock object used for locking
277 */
278 explicit inline TemporaryScopedLock(Lock& lock);
279
280 /**
281 * Destructs a scoped lock and unlocks the internal lock object (if still locked).
282 */
283 inline ~TemporaryScopedLock();
284
285 /**
286 * Returns the lock object which (if existing) is locked during the existence of this scoped lock object.
287 * @return The associated lock object, nullptr if this object is already released (or was never locked)
288 */
289 [[nodiscard]] inline Lock* lock() const;
290
291 /**
292 * Explicitly releases the lock before the scoped lock object is released.
293 */
294 inline void release();
295
296 /**
297 * Re-locks this scoped lock with a given lock.
298 * This scoped lock must be released before re-locking it again.
299 * @param lock The lock to be used for locking
300 * @see isReleased().
301 */
302 inline void relock(Lock& lock);
303
304 /**
305 * Returns whether this scoped lock is released already.
306 * @return True, if so
307 */
308 inline bool isReleased() const;
309
310 protected:
311
312 /**
313 * Disabled accessible copy operator.
314 * @param object The object to copy
315 */
316 inline TemporaryScopedLock(const TemporaryScopedLock& object) = delete;
317
318 /**
319 * Disabled accessible assigns operator.
320 * @param object The right object
321 * @return Reference to this object
322 */
323 inline TemporaryScopedLock& operator=(const TemporaryScopedLock& object) = delete;
324
325 protected:
326
327 /// Lock object which is locked during the existence of this scoped lock object.
328 Lock* lock_ = nullptr;
329};
330
331/**
332 * This class implements an optional recursive scoped lock object locking the lock object only if it's defined.
333 * @see Lock, ScopedLock, TemplatedScopedLock, TemporaryScopedLock.
334 * @ingroup base
335 */
336class OCEAN_BASE_EXPORT OptionalScopedLock
337{
338 public:
339
340 /**
341 * Creates a new optional scoped lock object by a given lock object.
342 * @param lock Optional lock object used for locking, otherwise nullptr
343 */
344 explicit inline OptionalScopedLock(Lock* lock);
345
346 /**
347 * Creates a new optional scoped lock object by a given lock object and a boolean statement whether the lock is invoked or not.
348 * @param lock The lock object used for locking
349 * @param apply True, to invoke the lock; False, to avoid the locking
350 */
351 inline OptionalScopedLock(Lock& lock, const bool apply);
352
353 /**
354 * Destructs an optional scoped lock and unlocks the internal lock object if defined.
355 */
356 inline ~OptionalScopedLock();
357
358 /**
359 * Returns the lock object which (if existing) is locked during the existence of this scoped lock object.
360 * @return The associated lock object, nullptr if no lock object was provided when this object was created
361 */
362 [[nodiscard]] inline Lock* lock() const;
363
364 protected:
365
366 /**
367 * Disabled accessible copy operator.
368 * @param object The object to copy
369 */
370 inline OptionalScopedLock(const OptionalScopedLock& object) = delete;
371
372 /**
373 * Disabled accessible assigns operator.
374 * @param object The right object
375 * @return Reference to this object
376 */
377 inline OptionalScopedLock& operator=(const OptionalScopedLock& object) = delete;
378
379 protected:
380
381 /// Lock object which is locked during the existence of this scoped lock object.
382 Lock* lock_ = nullptr;
383};
384
386{
387#if defined(_WINDOWS)
388
389 InitializeCriticalSection(&criticalSection_);
390
391#elif defined(__APPLE__) || defined(__linux__) || defined(__EMSCRIPTEN__)
392
393 pthread_mutexattr_t mutexAttribute;
394 pthread_mutexattr_init(&mutexAttribute);
395 pthread_mutexattr_settype(&mutexAttribute, PTHREAD_MUTEX_RECURSIVE);
396 pthread_mutex_init(&mutex_, &mutexAttribute);
397
398#else
399
400 pthread_mutexattr_t mutexAttribute = PTHREAD_MUTEX_RECURSIVE;
401 pthread_mutex_init(&mutex_, &mutexAttribute);
402
403#endif
404
405}
406
408{
409
410#if defined(_WINDOWS)
411
412 ocean_assert(criticalSection_.RecursionCount == 0);
413 DeleteCriticalSection(&criticalSection_);
414
415#else
416
417 pthread_mutex_destroy(&mutex_);
418
419#endif
420
421}
422
423inline void Lock::lock()
424{
425#if defined(_WINDOWS)
426
427 EnterCriticalSection(&criticalSection_);
428
429#else
430
431 pthread_mutex_lock(&mutex_);
432
433#endif
434
435}
436
437inline void Lock::unlock()
438{
439
440#if defined(_WINDOWS)
441
442 LeaveCriticalSection(&criticalSection_);
443
444#else
445
446 pthread_mutex_unlock(&mutex_);
447
448#endif
449
450}
451
452inline bool Lock::isLocked()
453{
454#if defined(_WINDOWS)
455
456 if (TryEnterCriticalSection(&criticalSection_) == TRUE)
457 {
458 LeaveCriticalSection(&criticalSection_);
459 return false;
460 }
461
462#else
463
464 if (pthread_mutex_trylock(&mutex_) == 0)
465 {
466 pthread_mutex_unlock(&mutex_);
467 return false;
468 }
469
470#endif
471
472 return true;
473}
474
476 lock_(lock)
477{
478 lock_.lock();
479}
480
482{
483 lock_.unlock();
484}
485
486template <bool tActive>
488 lock_(lock)
489{
490 lock_.lock();
491}
492
493template <bool tActive>
495 lock_(lock)
496{
497 lock.lock();
498}
499
500template <bool tActive>
502{
503 lock_.unlock();
504}
505
507 lock_(&lock)
508{
509 ocean_assert(lock_ != nullptr);
510 lock_->lock();
511}
512
514{
515 if (lock_ != nullptr)
516 {
517 lock_->unlock();
518 }
519}
520
522{
523 return lock_;
524}
525
527{
528 ocean_assert(!isReleased() && "This TemporaryScopedLock object has been released before");
529
530 if (lock_ != nullptr)
531 {
532 lock_->unlock();
533 lock_ = nullptr;
534 }
535}
536
538{
539 ocean_assert(isReleased() && "This TemporaryScopedLock object must be released before");
540
541 if (lock_ == nullptr)
542 {
543 lock_ = &lock;
544 lock_->lock();
545 }
546}
547
549{
550 return lock_ == nullptr;
551}
552
554 lock_(lock)
555{
556 if (lock_ != nullptr)
557 {
558 lock_->lock();
559 }
560}
561
562inline OptionalScopedLock::OptionalScopedLock(Lock& lock, const bool apply) :
563 lock_(nullptr)
564{
565 if (apply)
566 {
567 lock_ = &lock;
568 lock_->lock();
569 }
570}
571
573{
574 if (lock_ != nullptr)
575 {
576 lock_->unlock();
577 }
578}
579
581{
582 return lock_;
583}
584
585}
586
587#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:423
~Lock()
Destructs a lock object.
Definition Lock.h:407
bool isLocked()
Returns whether this critical section is locked by another thread.
Definition Lock.h:452
Lock & operator=(const Lock &lock)=delete
Disabled assign operator.
void unlock()
Unlocks the critical section.
Definition Lock.h:437
Lock(const Lock &lock)=delete
Disabled copy constructor.
Lock()
Creates a new lock object.
Definition Lock.h:385
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:337
~OptionalScopedLock()
Destructs an optional scoped lock and unlocks the internal lock object if defined.
Definition Lock.h:572
Lock * lock() const
Returns the lock object which (if existing) is locked during the existence of this scoped lock object...
Definition Lock.h:580
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:382
OptionalScopedLock(Lock *lock)
Creates a new optional scoped lock object by a given lock object.
Definition Lock.h:553
OptionalScopedLock(const OptionalScopedLock &object)=delete
Disabled accessible copy operator.
This class implements a scoped lock object for recursive lock objects.
Definition Lock.h:147
~ScopedLock()
Destructs a scoped lock and unlocks the internal lock object.
Definition Lock.h:481
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:475
Lock & lock_
Lock object which is locked during the existence of this scoped lock object.
Definition Lock.h:179
TemplatedLock & operator=(const TemplatedLock &lock)=delete
Disabled assign operator.
TemplatedLock(const TemplatedLock &lock)=delete
Disabled copy constructor.
TemplatedLock()=default
Creates a new lock object.
This class implements a template-based recursive lock object.
Definition Lock.h:99
TemplatedLock()=default
Creates a new lock object.
TemplatedScopedLock(Lock &lock)
Creates a new scoped lock object by a given lock object.
Definition Lock.h:245
TemplatedScopedLock(TemplatedLock< false > &lock)
Creates a new scoped lock object by a given lock object.
Definition Lock.h:254
This class implements a recursive scoped lock object that is activated by a boolean template paramete...
Definition Lock.h:190
TemplatedScopedLock(Lock &lock)
Creates a new scoped lock object by a given lock object.
Definition Lock.h:487
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:501
Lock & lock_
Lock object which is locked during the existence of this scoped lock object.
Definition Lock.h:228
This class implements a recursive scoped lock object allowing to release the lock before the scoped o...
Definition Lock.h:266
void relock(Lock &lock)
Re-locks this scoped lock with a given lock.
Definition Lock.h:537
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:521
void release()
Explicitly releases the lock before the scoped lock object is released.
Definition Lock.h:526
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:328
TemporaryScopedLock & operator=(const TemporaryScopedLock &object)=delete
Disabled accessible assigns operator.
bool isReleased() const
Returns whether this scoped lock is released already.
Definition Lock.h:548
~TemporaryScopedLock()
Destructs a scoped lock and unlocks the internal lock object (if still locked).
Definition Lock.h:513
The namespace covering the entire Ocean framework.
Definition Accessor.h:15