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.

346 lines
7.4KB

  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. class Signal;
  26. // -----------------------------------------------------------------------
  27. // Mutex class
  28. class Mutex
  29. {
  30. public:
  31. /*
  32. * Constructor.
  33. */
  34. Mutex(bool inheritPriority = true) noexcept
  35. : fMutex()
  36. {
  37. pthread_mutexattr_t attr;
  38. pthread_mutexattr_init(&attr);
  39. pthread_mutexattr_setprotocol(&attr, inheritPriority ? PTHREAD_PRIO_INHERIT : PTHREAD_PRIO_NONE);
  40. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
  41. pthread_mutex_init(&fMutex, &attr);
  42. pthread_mutexattr_destroy(&attr);
  43. }
  44. /*
  45. * Destructor.
  46. */
  47. ~Mutex() noexcept
  48. {
  49. pthread_mutex_destroy(&fMutex);
  50. }
  51. /*
  52. * Lock the mutex.
  53. */
  54. void lock() const noexcept
  55. {
  56. pthread_mutex_lock(&fMutex);
  57. }
  58. /*
  59. * Try to lock the mutex.
  60. * Returns true if successful.
  61. */
  62. bool tryLock() const noexcept
  63. {
  64. return (pthread_mutex_trylock(&fMutex) == 0);
  65. }
  66. /*
  67. * Unlock the mutex.
  68. */
  69. void unlock() const noexcept
  70. {
  71. pthread_mutex_unlock(&fMutex);
  72. }
  73. private:
  74. mutable pthread_mutex_t fMutex;
  75. friend class Signal;
  76. DISTRHO_PREVENT_HEAP_ALLOCATION
  77. DISTRHO_DECLARE_NON_COPY_CLASS(Mutex)
  78. };
  79. // -----------------------------------------------------------------------
  80. // RecursiveMutex class
  81. class RecursiveMutex
  82. {
  83. public:
  84. /*
  85. * Constructor.
  86. */
  87. RecursiveMutex() noexcept
  88. #ifdef DISTRHO_OS_WINDOWS
  89. : fSection()
  90. #else
  91. : fMutex()
  92. #endif
  93. {
  94. #ifdef DISTRHO_OS_WINDOWS
  95. InitializeCriticalSection(&fSection);
  96. #else
  97. pthread_mutexattr_t attr;
  98. pthread_mutexattr_init(&attr);
  99. pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
  100. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  101. pthread_mutex_init(&fMutex, &attr);
  102. pthread_mutexattr_destroy(&attr);
  103. #endif
  104. }
  105. /*
  106. * Destructor.
  107. */
  108. ~RecursiveMutex() noexcept
  109. {
  110. #ifdef DISTRHO_OS_WINDOWS
  111. DeleteCriticalSection(&fSection);
  112. #else
  113. pthread_mutex_destroy(&fMutex);
  114. #endif
  115. }
  116. /*
  117. * Lock the mutex.
  118. */
  119. void lock() const noexcept
  120. {
  121. #ifdef DISTRHO_OS_WINDOWS
  122. EnterCriticalSection(&fSection);
  123. #else
  124. pthread_mutex_lock(&fMutex);
  125. #endif
  126. }
  127. /*
  128. * Try to lock the mutex.
  129. * Returns true if successful.
  130. */
  131. bool tryLock() const noexcept
  132. {
  133. #ifdef DISTRHO_OS_WINDOWS
  134. return (TryEnterCriticalSection(&fSection) != FALSE);
  135. #else
  136. return (pthread_mutex_trylock(&fMutex) == 0);
  137. #endif
  138. }
  139. /*
  140. * Unlock the mutex.
  141. */
  142. void unlock() const noexcept
  143. {
  144. #ifdef DISTRHO_OS_WINDOWS
  145. LeaveCriticalSection(&fSection);
  146. #else
  147. pthread_mutex_unlock(&fMutex);
  148. #endif
  149. }
  150. private:
  151. #ifdef DISTRHO_OS_WINDOWS
  152. mutable CRITICAL_SECTION fSection;
  153. #else
  154. mutable pthread_mutex_t fMutex;
  155. #endif
  156. DISTRHO_PREVENT_HEAP_ALLOCATION
  157. DISTRHO_DECLARE_NON_COPY_CLASS(RecursiveMutex)
  158. };
  159. // -----------------------------------------------------------------------
  160. // Signal class
  161. class Signal
  162. {
  163. public:
  164. /*
  165. * Constructor.
  166. */
  167. Signal(Mutex& mutex) noexcept
  168. : fCondition(),
  169. fMutex(mutex.fMutex)
  170. {
  171. pthread_condattr_t attr;
  172. pthread_condattr_init(&attr);
  173. pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
  174. pthread_cond_init(&fCondition, &attr);
  175. pthread_condattr_destroy(&attr);
  176. }
  177. /*
  178. * Destructor.
  179. */
  180. ~Signal() noexcept
  181. {
  182. pthread_cond_destroy(&fCondition);
  183. }
  184. /*
  185. * Wait for a broadcast.
  186. */
  187. bool wait() noexcept
  188. {
  189. try {
  190. return (pthread_cond_wait(&fCondition, &fMutex) == 0);
  191. } DISTRHO_SAFE_EXCEPTION_RETURN("pthread_cond_wait", false);
  192. }
  193. /*
  194. * Wake up one waiting thread.
  195. */
  196. void signal() noexcept
  197. {
  198. pthread_cond_signal(&fCondition);
  199. }
  200. /*
  201. * Wake up all waiting threads.
  202. */
  203. void broadcast() noexcept
  204. {
  205. pthread_cond_broadcast(&fCondition);
  206. }
  207. private:
  208. pthread_cond_t fCondition;
  209. pthread_mutex_t& fMutex;
  210. DISTRHO_PREVENT_HEAP_ALLOCATION
  211. DISTRHO_DECLARE_NON_COPY_CLASS(Signal)
  212. };
  213. // -----------------------------------------------------------------------
  214. // Helper class to lock&unlock a mutex during a function scope.
  215. template <class Mutex>
  216. class ScopeLocker
  217. {
  218. public:
  219. ScopeLocker(const Mutex& mutex) noexcept
  220. : fMutex(mutex)
  221. {
  222. fMutex.lock();
  223. }
  224. ~ScopeLocker() noexcept
  225. {
  226. fMutex.unlock();
  227. }
  228. private:
  229. const Mutex& fMutex;
  230. DISTRHO_PREVENT_HEAP_ALLOCATION
  231. DISTRHO_DECLARE_NON_COPY_CLASS(ScopeLocker)
  232. };
  233. // -----------------------------------------------------------------------
  234. // Helper class to try-lock&unlock a mutex during a function scope.
  235. template <class Mutex>
  236. class ScopeTryLocker
  237. {
  238. public:
  239. ScopeTryLocker(const Mutex& mutex) noexcept
  240. : fMutex(mutex),
  241. fLocked(mutex.tryLock()) {}
  242. ~ScopeTryLocker() noexcept
  243. {
  244. if (fLocked)
  245. fMutex.unlock();
  246. }
  247. bool wasLocked() const noexcept
  248. {
  249. return fLocked;
  250. }
  251. bool wasNotLocked() const noexcept
  252. {
  253. return !fLocked;
  254. }
  255. private:
  256. const Mutex& fMutex;
  257. const bool fLocked;
  258. DISTRHO_PREVENT_HEAP_ALLOCATION
  259. DISTRHO_DECLARE_NON_COPY_CLASS(ScopeTryLocker)
  260. };
  261. // -----------------------------------------------------------------------
  262. // Helper class to unlock&lock a mutex during a function scope.
  263. template <class Mutex>
  264. class ScopeUnlocker
  265. {
  266. public:
  267. ScopeUnlocker(const Mutex& mutex) noexcept
  268. : fMutex(mutex)
  269. {
  270. fMutex.unlock();
  271. }
  272. ~ScopeUnlocker() noexcept
  273. {
  274. fMutex.lock();
  275. }
  276. private:
  277. const Mutex& fMutex;
  278. DISTRHO_PREVENT_HEAP_ALLOCATION
  279. DISTRHO_DECLARE_NON_COPY_CLASS(ScopeUnlocker)
  280. };
  281. // -----------------------------------------------------------------------
  282. // Define types
  283. typedef ScopeLocker<Mutex> MutexLocker;
  284. typedef ScopeLocker<RecursiveMutex> RecursiveMutexLocker;
  285. typedef ScopeTryLocker<Mutex> MutexTryLocker;
  286. typedef ScopeTryLocker<RecursiveMutex> RecursiveMutexTryLocker;
  287. typedef ScopeUnlocker<Mutex> MutexUnlocker;
  288. typedef ScopeUnlocker<RecursiveMutex> RecursiveMutexUnlocker;
  289. // -----------------------------------------------------------------------
  290. END_NAMESPACE_DISTRHO
  291. #endif // DISTRHO_MUTEX_HPP_INCLUDED