The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
9.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2016 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of the ISC license
  6. http://www.isc.org/downloads/software-support-policy/isc-license/
  7. Permission to use, copy, modify, and/or distribute this software for any
  8. purpose with or without fee is hereby granted, provided that the above
  9. copyright notice and this permission notice appear in all copies.
  10. THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
  11. TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  12. FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
  13. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  14. USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  16. OF THIS SOFTWARE.
  17. -----------------------------------------------------------------------------
  18. To release a closed-source product which uses other parts of JUCE not
  19. licensed under the ISC terms, commercial licenses are available: visit
  20. www.juce.com for more information.
  21. ==============================================================================
  22. */
  23. #ifndef JUCE_CRITICALSECTION_H_INCLUDED
  24. #define JUCE_CRITICALSECTION_H_INCLUDED
  25. //==============================================================================
  26. /**
  27. A re-entrant mutex.
  28. A CriticalSection acts as a re-entrant mutex object. The best way to lock and unlock
  29. one of these is by using RAII in the form of a local ScopedLock object - have a look
  30. through the codebase for many examples of how to do this.
  31. In almost all cases you'll want to declare your CriticalSection as a member variable.
  32. Occasionally you may want to declare one as a static variable, but in that case the usual
  33. C++ static object order-of-construction warnings should be heeded.
  34. @see ScopedLock, ScopedTryLock, ScopedUnlock, SpinLock, ReadWriteLock, Thread, InterProcessLock
  35. */
  36. class JUCE_API CriticalSection
  37. {
  38. public:
  39. //==============================================================================
  40. /** Creates a CriticalSection object. */
  41. CriticalSection() noexcept;
  42. /** Destructor.
  43. If the critical section is deleted whilst locked, any subsequent behaviour
  44. is unpredictable.
  45. */
  46. ~CriticalSection() noexcept;
  47. //==============================================================================
  48. /** Acquires the lock.
  49. If the lock is already held by the caller thread, the method returns immediately.
  50. If the lock is currently held by another thread, this will wait until it becomes free.
  51. It's strongly recommended that you never call this method directly - instead use the
  52. ScopedLock class to manage the locking using an RAII pattern instead.
  53. @see exit, tryEnter, ScopedLock
  54. */
  55. void enter() const noexcept;
  56. /** Attempts to lock this critical section without blocking.
  57. This method behaves identically to CriticalSection::enter, except that the caller thread
  58. does not wait if the lock is currently held by another thread but returns false immediately.
  59. @returns false if the lock is currently held by another thread, true otherwise.
  60. @see enter
  61. */
  62. bool tryEnter() const noexcept;
  63. /** Releases the lock.
  64. If the caller thread hasn't got the lock, this can have unpredictable results.
  65. If the enter() method has been called multiple times by the thread, each
  66. call must be matched by a call to exit() before other threads will be allowed
  67. to take over the lock.
  68. @see enter, ScopedLock
  69. */
  70. void exit() const noexcept;
  71. //==============================================================================
  72. /** Provides the type of scoped lock to use with a CriticalSection. */
  73. typedef GenericScopedLock <CriticalSection> ScopedLockType;
  74. /** Provides the type of scoped unlocker to use with a CriticalSection. */
  75. typedef GenericScopedUnlock <CriticalSection> ScopedUnlockType;
  76. /** Provides the type of scoped try-locker to use with a CriticalSection. */
  77. typedef GenericScopedTryLock <CriticalSection> ScopedTryLockType;
  78. private:
  79. //==============================================================================
  80. #if JUCE_WINDOWS
  81. // To avoid including windows.h in the public JUCE headers, we'll just allocate
  82. // a block of memory here that's big enough to be used internally as a windows
  83. // CRITICAL_SECTION structure.
  84. #if JUCE_64BIT
  85. uint8 lock[44];
  86. #else
  87. uint8 lock[24];
  88. #endif
  89. #else
  90. mutable pthread_mutex_t lock;
  91. #endif
  92. JUCE_DECLARE_NON_COPYABLE (CriticalSection)
  93. };
  94. //==============================================================================
  95. /**
  96. A class that can be used in place of a real CriticalSection object, but which
  97. doesn't perform any locking.
  98. This is currently used by some templated classes, and most compilers should
  99. manage to optimise it out of existence.
  100. @see CriticalSection, Array, OwnedArray, ReferenceCountedArray
  101. */
  102. class JUCE_API DummyCriticalSection
  103. {
  104. public:
  105. inline DummyCriticalSection() noexcept {}
  106. inline ~DummyCriticalSection() noexcept {}
  107. inline void enter() const noexcept {}
  108. inline bool tryEnter() const noexcept { return true; }
  109. inline void exit() const noexcept {}
  110. //==============================================================================
  111. /** A dummy scoped-lock type to use with a dummy critical section. */
  112. struct ScopedLockType
  113. {
  114. ScopedLockType (const DummyCriticalSection&) noexcept {}
  115. };
  116. /** A dummy scoped-unlocker type to use with a dummy critical section. */
  117. typedef ScopedLockType ScopedUnlockType;
  118. private:
  119. JUCE_DECLARE_NON_COPYABLE (DummyCriticalSection)
  120. };
  121. //==============================================================================
  122. /**
  123. Automatically locks and unlocks a CriticalSection object.
  124. You can use a ScopedLock as a local variable to provide RAII-based locking of a CriticalSection.
  125. e.g. @code
  126. struct MyObject
  127. {
  128. CriticalSection objectLock;
  129. // assuming that this example function will be called by multiple threads
  130. void foo()
  131. {
  132. const ScopedLock myScopedLock (objectLock);
  133. // objectLock is now locked..
  134. ...do some thread-safe work here...
  135. // ..and objectLock gets unlocked here, as myScopedLock goes out of
  136. // scope at the end of the block
  137. }
  138. };
  139. @endcode
  140. @see CriticalSection, ScopedUnlock
  141. */
  142. typedef CriticalSection::ScopedLockType ScopedLock;
  143. //==============================================================================
  144. /**
  145. Automatically unlocks and re-locks a CriticalSection object.
  146. This is the reverse of a ScopedLock object - instead of locking the critical
  147. section for the lifetime of this object, it unlocks it.
  148. Make sure you don't try to unlock critical sections that aren't actually locked!
  149. e.g. @code
  150. struct MyObject
  151. {
  152. CriticalSection objectLock;
  153. void foo()
  154. {
  155. {
  156. const ScopedLock myScopedLock (objectLock);
  157. // objectLock is now locked..
  158. {
  159. ScopedUnlock myUnlocker (objectLock);
  160. // ..and now unlocked..
  161. }
  162. // ..and now locked again..
  163. }
  164. // ..and finally unlocked.
  165. }
  166. };
  167. @endcode
  168. @see CriticalSection, ScopedLock
  169. */
  170. typedef CriticalSection::ScopedUnlockType ScopedUnlock;
  171. //==============================================================================
  172. /**
  173. Automatically tries to lock and unlock a CriticalSection object.
  174. Use one of these as a local variable to control access to a CriticalSection.
  175. e.g. @code
  176. struct MyObject
  177. {
  178. CriticalSection objectLock;
  179. void foo()
  180. {
  181. const ScopedTryLock myScopedTryLock (objectLock);
  182. // Unlike using a ScopedLock, this may fail to actually get the lock, so you
  183. // must call the isLocked() method before making any assumptions..
  184. if (myScopedTryLock.isLocked())
  185. {
  186. ...safely do some work...
  187. }
  188. else
  189. {
  190. // If we get here, then our attempt at locking failed because another thread had already locked it..
  191. }
  192. }
  193. };
  194. @endcode
  195. @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock
  196. */
  197. typedef CriticalSection::ScopedTryLockType ScopedTryLock;
  198. #endif // JUCE_CRITICALSECTION_H_INCLUDED