Ocean
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 
20 namespace 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  */
30 class 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  */
97 template <bool tActive>
98 class 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  */
108 template <>
109 class TemplatedLock<false>
110 {
111  protected:
112 
113  /**
114  * Disabled copy constructor.
115  * @param lock The lock object to be copied
116  */
117  TemplatedLock(const TemplatedLock& lock) = delete;
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  */
134 class 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  */
176 template <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  */
224 template <>
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  */
253 class OCEAN_BASE_EXPORT TemporaryScopedLock
254 {
255  public:
256 
257  /**
258  * Creates a new scoped lock object which is not locked yet.
259  */
260  TemporaryScopedLock() = default;
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  */
324 class 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 
373 inline Lock::Lock()
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 
395 inline Lock::~Lock()
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 
411 inline 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 
425 inline 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 
440 inline 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 
474 template <bool tActive>
476  lock_(lock)
477 {
478  lock_.lock();
479 }
480 
481 template <bool tActive>
483  lock_(lock)
484 {
485  lock.lock();
486 }
487 
488 template <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 
550 inline 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
OptionalScopedLock & operator=(const OptionalScopedLock &object)=delete
Disabled accessible assigns operator.
Lock * lock() const
Returns the lock object which (if existing) is locked during the existence of this scoped lock object...
Definition: Lock.h:568
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
Specialization of the TemplatedLock class.
Definition: Lock.h:110
TemplatedLock(const TemplatedLock &lock)=delete
Disabled copy constructor.
TemplatedLock & operator=(const TemplatedLock &lock)=delete
Disabled assign operator.
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 & operator=(const TemporaryScopedLock &object)=delete
Disabled accessible assigns operator.
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
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
void release(T *object)
This functions allows to release a DirectShow object if it does exist.
Definition: DSObject.h:266
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15