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.

258 lines
8.7KB

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