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.

284 lines
6.1KB

  1. /*
  2. * Carla Mutex
  3. * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_MUTEX_HPP_INCLUDED
  18. #define CARLA_MUTEX_HPP_INCLUDED
  19. #include "CarlaUtils.hpp"
  20. #include <pthread.h>
  21. // -----------------------------------------------------------------------
  22. // CarlaMutex class
  23. class CarlaMutex
  24. {
  25. public:
  26. /*
  27. * Constructor.
  28. */
  29. CarlaMutex() noexcept
  30. : fMutex(),
  31. fTryLockWasCalled(false)
  32. {
  33. pthread_mutex_init(&fMutex, nullptr);
  34. }
  35. /*
  36. * Destructor.
  37. */
  38. ~CarlaMutex() noexcept
  39. {
  40. pthread_mutex_destroy(&fMutex);
  41. }
  42. /*
  43. * Check if "tryLock()" was called before.
  44. */
  45. bool wasTryLockCalled() const noexcept
  46. {
  47. const bool ret(fTryLockWasCalled);
  48. fTryLockWasCalled = false;
  49. return ret;
  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. fTryLockWasCalled = true;
  65. return (pthread_mutex_trylock(&fMutex) == 0);
  66. }
  67. /*
  68. * Unlock the mutex, optionally resetting the tryLock check.
  69. */
  70. void unlock(const bool resetTryLock = false) const noexcept
  71. {
  72. if (resetTryLock)
  73. fTryLockWasCalled = false;
  74. pthread_mutex_unlock(&fMutex);
  75. }
  76. private:
  77. mutable pthread_mutex_t fMutex; // The mutex
  78. mutable volatile bool fTryLockWasCalled; // true if "tryLock()" was called at least once
  79. CARLA_PREVENT_HEAP_ALLOCATION
  80. CARLA_DECLARE_NON_COPY_CLASS(CarlaMutex)
  81. };
  82. // -----------------------------------------------------------------------
  83. // CarlaRecursiveMutex class
  84. class CarlaRecursiveMutex
  85. {
  86. public:
  87. /*
  88. * Constructor.
  89. */
  90. CarlaRecursiveMutex() noexcept
  91. #ifdef CARLA_OS_WIN
  92. : fSection()
  93. #else
  94. : fMutex()
  95. #endif
  96. {
  97. #ifdef CARLA_OS_WIN
  98. InitializeCriticalSection(&fSection);
  99. #else
  100. pthread_mutexattr_t atts;
  101. pthread_mutexattr_init(&atts);
  102. pthread_mutexattr_settype(&atts, PTHREAD_MUTEX_RECURSIVE);
  103. pthread_mutex_init(&fMutex, &atts);
  104. pthread_mutexattr_destroy(&atts);
  105. #endif
  106. }
  107. /*
  108. * Destructor.
  109. */
  110. ~CarlaRecursiveMutex() noexcept
  111. {
  112. #ifdef CARLA_OS_WIN
  113. DeleteCriticalSection(&fSection);
  114. #else
  115. pthread_mutex_destroy(&fMutex);
  116. #endif
  117. }
  118. /*
  119. * Lock the mutex.
  120. */
  121. void lock() const noexcept
  122. {
  123. #ifdef CARLA_OS_WIN
  124. EnterCriticalSection(&fSection);
  125. #else
  126. pthread_mutex_lock(&fMutex);
  127. #endif
  128. }
  129. /*
  130. * Try to lock the mutex.
  131. * Returns true if successful.
  132. */
  133. bool tryLock() const noexcept
  134. {
  135. #ifdef CARLA_OS_WIN
  136. return (TryEnterCriticalSection(&fSection) != FALSE);
  137. #else
  138. return (pthread_mutex_trylock(&fMutex) == 0);
  139. #endif
  140. }
  141. /*
  142. * Unlock the mutex.
  143. */
  144. void unlock() const noexcept
  145. {
  146. #ifdef CARLA_OS_WIN
  147. LeaveCriticalSection(&fSection);
  148. #else
  149. pthread_mutex_unlock(&fMutex);
  150. #endif
  151. }
  152. private:
  153. #ifdef CARLA_OS_WIN
  154. mutable CRITICAL_SECTION fSection;
  155. #else
  156. mutable pthread_mutex_t fMutex;
  157. #endif
  158. CARLA_PREVENT_HEAP_ALLOCATION
  159. CARLA_DECLARE_NON_COPY_CLASS(CarlaRecursiveMutex)
  160. };
  161. // -----------------------------------------------------------------------
  162. // Helper class to lock&unlock a mutex during a function scope.
  163. template <class Mutex>
  164. class CarlaScopeLocker
  165. {
  166. public:
  167. CarlaScopeLocker(const Mutex& mutex) noexcept
  168. : fMutex(mutex)
  169. {
  170. fMutex.lock();
  171. }
  172. ~CarlaScopeLocker() noexcept
  173. {
  174. fMutex.unlock();
  175. }
  176. private:
  177. const Mutex& fMutex;
  178. CARLA_PREVENT_HEAP_ALLOCATION
  179. CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeLocker)
  180. };
  181. // -----------------------------------------------------------------------
  182. // Helper class to try-lock&unlock a mutex during a function scope.
  183. template <class Mutex>
  184. class CarlaScopeTryLocker
  185. {
  186. public:
  187. CarlaScopeTryLocker(const Mutex& mutex) noexcept
  188. : fMutex(mutex),
  189. fLocked(mutex.tryLock()) {}
  190. ~CarlaScopeTryLocker() noexcept
  191. {
  192. if (fLocked)
  193. fMutex.unlock();
  194. }
  195. bool wasLocked() const noexcept
  196. {
  197. return fLocked;
  198. }
  199. bool wasNotLocked() const noexcept
  200. {
  201. return !fLocked;
  202. }
  203. private:
  204. const Mutex& fMutex;
  205. const bool fLocked;
  206. CARLA_PREVENT_HEAP_ALLOCATION
  207. CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeTryLocker)
  208. };
  209. // -----------------------------------------------------------------------
  210. // Helper class to unlock&lock a mutex during a function scope.
  211. template <class Mutex>
  212. class CarlaScopeUnlocker
  213. {
  214. public:
  215. CarlaScopeUnlocker(const Mutex& mutex) noexcept
  216. : fMutex(mutex)
  217. {
  218. fMutex.unlock();
  219. }
  220. ~CarlaScopeUnlocker() noexcept
  221. {
  222. fMutex.lock();
  223. }
  224. private:
  225. const Mutex& fMutex;
  226. CARLA_PREVENT_HEAP_ALLOCATION
  227. CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeUnlocker)
  228. };
  229. // -----------------------------------------------------------------------
  230. // Define types
  231. typedef CarlaScopeLocker<CarlaMutex> CarlaMutexLocker;
  232. typedef CarlaScopeLocker<CarlaRecursiveMutex> CarlaRecursiveMutexLocker;
  233. typedef CarlaScopeTryLocker<CarlaMutex> CarlaMutexTryLocker;
  234. typedef CarlaScopeTryLocker<CarlaRecursiveMutex> CarlaRecursiveMutexTryLocker;
  235. typedef CarlaScopeUnlocker<CarlaMutex> CarlaMutexUnlocker;
  236. typedef CarlaScopeUnlocker<CarlaRecursiveMutex> CarlaRecursiveMutexUnlocker;
  237. // -----------------------------------------------------------------------
  238. #endif // CARLA_MUTEX_HPP_INCLUDED