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.

Mutex.hpp 7.9KB

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