Audio plugin host https://kx.studio/carla
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.

281 lines
6.1KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
  4. *
  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. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef DISTRHO_MUTEX_HPP_INCLUDED
  17. #define DISTRHO_MUTEX_HPP_INCLUDED
  18. #include "../DistrhoUtils.hpp"
  19. #ifdef DISTRHO_OS_WINDOWS
  20. # include <winsock2.h>
  21. # include <windows.h>
  22. #endif
  23. #include <pthread.h>
  24. START_NAMESPACE_DISTRHO
  25. // -----------------------------------------------------------------------
  26. // Mutex class
  27. class Mutex
  28. {
  29. public:
  30. /*
  31. * Constructor.
  32. */
  33. Mutex() noexcept
  34. : fMutex()
  35. {
  36. pthread_mutexattr_t atts;
  37. pthread_mutexattr_init(&atts);
  38. pthread_mutexattr_setprotocol(&atts, PTHREAD_PRIO_INHERIT);
  39. pthread_mutexattr_settype(&atts, PTHREAD_MUTEX_NORMAL);
  40. pthread_mutex_init(&fMutex, &atts);
  41. pthread_mutexattr_destroy(&atts);
  42. }
  43. /*
  44. * Destructor.
  45. */
  46. ~Mutex() noexcept
  47. {
  48. pthread_mutex_destroy(&fMutex);
  49. }
  50. /*
  51. * Lock the mutex.
  52. */
  53. void lock() const noexcept
  54. {
  55. pthread_mutex_lock(&fMutex);
  56. }
  57. /*
  58. * Try to lock the mutex.
  59. * Returns true if successful.
  60. */
  61. bool tryLock() const noexcept
  62. {
  63. return (pthread_mutex_trylock(&fMutex) == 0);
  64. }
  65. /*
  66. * Unlock the mutex.
  67. */
  68. void unlock() const noexcept
  69. {
  70. pthread_mutex_unlock(&fMutex);
  71. }
  72. private:
  73. mutable pthread_mutex_t fMutex;
  74. DISTRHO_PREVENT_HEAP_ALLOCATION
  75. DISTRHO_DECLARE_NON_COPY_CLASS(Mutex)
  76. };
  77. // -----------------------------------------------------------------------
  78. // RecursiveMutex class
  79. class RecursiveMutex
  80. {
  81. public:
  82. /*
  83. * Constructor.
  84. */
  85. RecursiveMutex() noexcept
  86. #ifdef DISTRHO_OS_WINDOWS
  87. : fSection()
  88. #else
  89. : fMutex()
  90. #endif
  91. {
  92. #ifdef DISTRHO_OS_WINDOWS
  93. InitializeCriticalSection(&fSection);
  94. #else
  95. pthread_mutexattr_t atts;
  96. pthread_mutexattr_init(&atts);
  97. pthread_mutexattr_setprotocol(&atts, PTHREAD_PRIO_INHERIT);
  98. pthread_mutexattr_settype(&atts, PTHREAD_MUTEX_RECURSIVE);
  99. pthread_mutex_init(&fMutex, &atts);
  100. pthread_mutexattr_destroy(&atts);
  101. #endif
  102. }
  103. /*
  104. * Destructor.
  105. */
  106. ~RecursiveMutex() noexcept
  107. {
  108. #ifdef DISTRHO_OS_WINDOWS
  109. DeleteCriticalSection(&fSection);
  110. #else
  111. pthread_mutex_destroy(&fMutex);
  112. #endif
  113. }
  114. /*
  115. * Lock the mutex.
  116. */
  117. void lock() const noexcept
  118. {
  119. #ifdef DISTRHO_OS_WINDOWS
  120. EnterCriticalSection(&fSection);
  121. #else
  122. pthread_mutex_lock(&fMutex);
  123. #endif
  124. }
  125. /*
  126. * Try to lock the mutex.
  127. * Returns true if successful.
  128. */
  129. bool tryLock() const noexcept
  130. {
  131. #ifdef DISTRHO_OS_WINDOWS
  132. return (TryEnterCriticalSection(&fSection) != FALSE);
  133. #else
  134. return (pthread_mutex_trylock(&fMutex) == 0);
  135. #endif
  136. }
  137. /*
  138. * Unlock the mutex.
  139. */
  140. void unlock() const noexcept
  141. {
  142. #ifdef DISTRHO_OS_WINDOWS
  143. LeaveCriticalSection(&fSection);
  144. #else
  145. pthread_mutex_unlock(&fMutex);
  146. #endif
  147. }
  148. private:
  149. #ifdef DISTRHO_OS_WINDOWS
  150. mutable CRITICAL_SECTION fSection;
  151. #else
  152. mutable pthread_mutex_t fMutex;
  153. #endif
  154. DISTRHO_PREVENT_HEAP_ALLOCATION
  155. DISTRHO_DECLARE_NON_COPY_CLASS(RecursiveMutex)
  156. };
  157. // -----------------------------------------------------------------------
  158. // Helper class to lock&unlock a mutex during a function scope.
  159. template <class Mutex>
  160. class ScopeLocker
  161. {
  162. public:
  163. ScopeLocker(const Mutex& mutex) noexcept
  164. : fMutex(mutex)
  165. {
  166. fMutex.lock();
  167. }
  168. ~ScopeLocker() noexcept
  169. {
  170. fMutex.unlock();
  171. }
  172. private:
  173. const Mutex& fMutex;
  174. DISTRHO_PREVENT_HEAP_ALLOCATION
  175. DISTRHO_DECLARE_NON_COPY_CLASS(ScopeLocker)
  176. };
  177. // -----------------------------------------------------------------------
  178. // Helper class to try-lock&unlock a mutex during a function scope.
  179. template <class Mutex>
  180. class ScopeTryLocker
  181. {
  182. public:
  183. ScopeTryLocker(const Mutex& mutex) noexcept
  184. : fMutex(mutex),
  185. fLocked(mutex.tryLock()) {}
  186. ~ScopeTryLocker() noexcept
  187. {
  188. if (fLocked)
  189. fMutex.unlock();
  190. }
  191. bool wasLocked() const noexcept
  192. {
  193. return fLocked;
  194. }
  195. bool wasNotLocked() const noexcept
  196. {
  197. return !fLocked;
  198. }
  199. private:
  200. const Mutex& fMutex;
  201. const bool fLocked;
  202. DISTRHO_PREVENT_HEAP_ALLOCATION
  203. DISTRHO_DECLARE_NON_COPY_CLASS(ScopeTryLocker)
  204. };
  205. // -----------------------------------------------------------------------
  206. // Helper class to unlock&lock a mutex during a function scope.
  207. template <class Mutex>
  208. class ScopeUnlocker
  209. {
  210. public:
  211. ScopeUnlocker(const Mutex& mutex) noexcept
  212. : fMutex(mutex)
  213. {
  214. fMutex.unlock();
  215. }
  216. ~ScopeUnlocker() noexcept
  217. {
  218. fMutex.lock();
  219. }
  220. private:
  221. const Mutex& fMutex;
  222. DISTRHO_PREVENT_HEAP_ALLOCATION
  223. DISTRHO_DECLARE_NON_COPY_CLASS(ScopeUnlocker)
  224. };
  225. // -----------------------------------------------------------------------
  226. // Define types
  227. typedef ScopeLocker<Mutex> MutexLocker;
  228. typedef ScopeLocker<RecursiveMutex> RecursiveMutexLocker;
  229. typedef ScopeTryLocker<Mutex> MutexTryLocker;
  230. typedef ScopeTryLocker<RecursiveMutex> RecursiveMutexTryLocker;
  231. typedef ScopeUnlocker<Mutex> MutexUnlocker;
  232. typedef ScopeUnlocker<RecursiveMutex> RecursiveMutexUnlocker;
  233. // -----------------------------------------------------------------------
  234. END_NAMESPACE_DISTRHO
  235. #endif // DISTRHO_MUTEX_HPP_INCLUDED