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.

255 lines
8.5KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #ifndef __JUCE_CRITICALSECTION_JUCEHEADER__
  19. #define __JUCE_CRITICALSECTION_JUCEHEADER__
  20. #include "juce_ScopedLock.h"
  21. //==============================================================================
  22. /**
  23. A mutex class.
  24. A CriticalSection acts as a re-entrant mutex lock. The best way to lock and unlock
  25. one of these is by using RAII in the form of a local ScopedLock object - have a look
  26. through the codebase for many examples of how to do this.
  27. @see ScopedLock, ScopedTryLock, ScopedUnlock, SpinLock, ReadWriteLock, Thread, InterProcessLock
  28. */
  29. class JUCE_API CriticalSection
  30. {
  31. public:
  32. //==============================================================================
  33. /** Creates a CriticalSection object. */
  34. CriticalSection() noexcept;
  35. /** Destructor.
  36. If the critical section is deleted whilst locked, any subsequent behaviour
  37. is unpredictable.
  38. */
  39. ~CriticalSection() noexcept;
  40. //==============================================================================
  41. /** Acquires the lock.
  42. If the lock is already held by the caller thread, the method returns immediately.
  43. If the lock is currently held by another thread, this will wait until it becomes free.
  44. It's strongly recommended that you never call this method directly - instead use the
  45. ScopedLock class to manage the locking using an RAII pattern instead.
  46. @see exit, tryEnter, ScopedLock
  47. */
  48. void enter() const noexcept;
  49. /** Attempts to lock this critical section without blocking.
  50. This method behaves identically to CriticalSection::enter, except that the caller thread
  51. does not wait if the lock is currently held by another thread but returns false immediately.
  52. @returns false if the lock is currently held by another thread, true otherwise.
  53. @see enter
  54. */
  55. bool tryEnter() const noexcept;
  56. /** Releases the lock.
  57. If the caller thread hasn't got the lock, this can have unpredictable results.
  58. If the enter() method has been called multiple times by the thread, each
  59. call must be matched by a call to exit() before other threads will be allowed
  60. to take over the lock.
  61. @see enter, ScopedLock
  62. */
  63. void exit() const noexcept;
  64. //==============================================================================
  65. /** Provides the type of scoped lock to use with a CriticalSection. */
  66. typedef GenericScopedLock <CriticalSection> ScopedLockType;
  67. /** Provides the type of scoped unlocker to use with a CriticalSection. */
  68. typedef GenericScopedUnlock <CriticalSection> ScopedUnlockType;
  69. /** Provides the type of scoped try-locker to use with a CriticalSection. */
  70. typedef GenericScopedTryLock <CriticalSection> ScopedTryLockType;
  71. private:
  72. //==============================================================================
  73. #if JUCE_WINDOWS
  74. // To avoid including windows.h in the public JUCE headers, we'll just allocate a
  75. // block of memory here that's big enough to be used internally as a windows critical
  76. // section structure.
  77. #if JUCE_64BIT
  78. uint8 internal [44];
  79. #else
  80. uint8 internal [24];
  81. #endif
  82. #else
  83. mutable pthread_mutex_t internal;
  84. #endif
  85. JUCE_DECLARE_NON_COPYABLE (CriticalSection);
  86. };
  87. //==============================================================================
  88. /**
  89. A class that can be used in place of a real CriticalSection object, but which
  90. doesn't perform any locking.
  91. This is currently used by some templated classes, and most compilers should
  92. manage to optimise it out of existence.
  93. @see CriticalSection, Array, OwnedArray, ReferenceCountedArray
  94. */
  95. class JUCE_API DummyCriticalSection
  96. {
  97. public:
  98. inline DummyCriticalSection() noexcept {}
  99. inline ~DummyCriticalSection() noexcept {}
  100. inline void enter() const noexcept {}
  101. inline bool tryEnter() const noexcept { return true; }
  102. inline void exit() const noexcept {}
  103. //==============================================================================
  104. /** A dummy scoped-lock type to use with a dummy critical section. */
  105. struct ScopedLockType
  106. {
  107. ScopedLockType (const DummyCriticalSection&) noexcept {}
  108. };
  109. /** A dummy scoped-unlocker type to use with a dummy critical section. */
  110. typedef ScopedLockType ScopedUnlockType;
  111. private:
  112. JUCE_DECLARE_NON_COPYABLE (DummyCriticalSection);
  113. };
  114. //==============================================================================
  115. /**
  116. Automatically locks and unlocks a CriticalSection object.
  117. Use one of these as a local variable to provide RAII-based locking of a CriticalSection.
  118. e.g. @code
  119. CriticalSection myCriticalSection;
  120. for (;;)
  121. {
  122. const ScopedLock myScopedLock (myCriticalSection);
  123. // myCriticalSection is now locked
  124. ...do some stuff...
  125. // myCriticalSection gets unlocked here.
  126. }
  127. @endcode
  128. @see CriticalSection, ScopedUnlock
  129. */
  130. typedef CriticalSection::ScopedLockType ScopedLock;
  131. //==============================================================================
  132. /**
  133. Automatically unlocks and re-locks a CriticalSection object.
  134. This is the reverse of a ScopedLock object - instead of locking the critical
  135. section for the lifetime of this object, it unlocks it.
  136. Make sure you don't try to unlock critical sections that aren't actually locked!
  137. e.g. @code
  138. CriticalSection myCriticalSection;
  139. for (;;)
  140. {
  141. const ScopedLock myScopedLock (myCriticalSection);
  142. // myCriticalSection is now locked
  143. ... do some stuff with it locked ..
  144. while (xyz)
  145. {
  146. ... do some stuff with it locked ..
  147. const ScopedUnlock unlocker (myCriticalSection);
  148. // myCriticalSection is now unlocked for the remainder of this block,
  149. // and re-locked at the end.
  150. ...do some stuff with it unlocked ...
  151. }
  152. // myCriticalSection gets unlocked here.
  153. }
  154. @endcode
  155. @see CriticalSection, ScopedLock
  156. */
  157. typedef CriticalSection::ScopedUnlockType ScopedUnlock;
  158. //==============================================================================
  159. /**
  160. Automatically tries to lock and unlock a CriticalSection object.
  161. Use one of these as a local variable to control access to a CriticalSection.
  162. e.g. @code
  163. CriticalSection myCriticalSection;
  164. for (;;)
  165. {
  166. const ScopedTryLock myScopedTryLock (myCriticalSection);
  167. // Unlike using a ScopedLock, this may fail to actually get the lock, so you
  168. // should test this with the isLocked() method before doing your thread-unsafe
  169. // action..
  170. if (myScopedTryLock.isLocked())
  171. {
  172. ...do some stuff...
  173. }
  174. else
  175. {
  176. ..our attempt at locking failed because another thread had already locked it..
  177. }
  178. // myCriticalSection gets unlocked here (if it was locked)
  179. }
  180. @endcode
  181. @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock
  182. */
  183. typedef CriticalSection::ScopedTryLockType ScopedTryLock;
  184. #endif // __JUCE_CRITICALSECTION_JUCEHEADER__