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.

268 lines
5.9KB

  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. : fTryLockWasCalled(false)
  31. {
  32. pthread_mutex_init(&fMutex, nullptr);
  33. }
  34. /*
  35. * Destructor.
  36. */
  37. ~CarlaMutex() noexcept
  38. {
  39. pthread_mutex_destroy(&fMutex);
  40. }
  41. /*
  42. * Check if "tryLock()" was called before.
  43. */
  44. bool wasTryLockCalled() const noexcept
  45. {
  46. const bool ret(fTryLockWasCalled);
  47. fTryLockWasCalled = false;
  48. return ret;
  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. fTryLockWasCalled = true;
  64. return (pthread_mutex_trylock(&fMutex) == 0);
  65. }
  66. /*
  67. * Unlock the mutex, optionally resetting the tryLock check.
  68. */
  69. void unlock(const bool resetTryLock = false) const noexcept
  70. {
  71. if (resetTryLock)
  72. fTryLockWasCalled = false;
  73. pthread_mutex_unlock(&fMutex);
  74. }
  75. private:
  76. mutable pthread_mutex_t fMutex; // The mutex
  77. mutable volatile bool fTryLockWasCalled; // true if "tryLock()" was called at least once
  78. CARLA_PREVENT_HEAP_ALLOCATION
  79. CARLA_DECLARE_NON_COPY_CLASS(CarlaMutex)
  80. };
  81. // -----------------------------------------------------------------------
  82. // CarlaRecursiveMutex class
  83. class CarlaRecursiveMutex
  84. {
  85. public:
  86. /*
  87. * Constructor.
  88. */
  89. CarlaRecursiveMutex() noexcept
  90. {
  91. #ifdef CARLA_OS_WIN
  92. InitializeCriticalSection(&fSection);
  93. #else
  94. pthread_mutexattr_t atts;
  95. pthread_mutexattr_init(&atts);
  96. pthread_mutexattr_settype(&atts, PTHREAD_MUTEX_RECURSIVE);
  97. pthread_mutex_init(&fMutex, &atts);
  98. pthread_mutexattr_destroy(&atts);
  99. #endif
  100. }
  101. /*
  102. * Destructor.
  103. */
  104. ~CarlaRecursiveMutex() noexcept
  105. {
  106. #ifdef CARLA_OS_WIN
  107. DeleteCriticalSection(&fSection);
  108. #else
  109. pthread_mutex_destroy(&fMutex);
  110. #endif
  111. }
  112. /*
  113. * Lock the mutex.
  114. */
  115. void lock() const noexcept
  116. {
  117. #ifdef CARLA_OS_WIN
  118. EnterCriticalSection(&fSection);
  119. #else
  120. pthread_mutex_lock(&fMutex);
  121. #endif
  122. }
  123. /*
  124. * Try to lock the mutex.
  125. * Returns true if successful.
  126. */
  127. bool tryLock() const noexcept
  128. {
  129. #ifdef CARLA_OS_WIN
  130. return (TryEnterCriticalSection(&fSection) != FALSE);
  131. #else
  132. return (pthread_mutex_trylock(&fMutex) == 0);
  133. #endif
  134. }
  135. /*
  136. * Unlock the mutex.
  137. */
  138. void unlock() const noexcept
  139. {
  140. #ifdef CARLA_OS_WIN
  141. LeaveCriticalSection(&fSection);
  142. #else
  143. pthread_mutex_unlock(&fMutex);
  144. #endif
  145. }
  146. private:
  147. #ifdef CARLA_OS_WIN
  148. mutable CRITICAL_SECTION fSection;
  149. #else
  150. mutable pthread_mutex_t fMutex;
  151. #endif
  152. CARLA_PREVENT_HEAP_ALLOCATION
  153. CARLA_DECLARE_NON_COPY_CLASS(CarlaRecursiveMutex)
  154. };
  155. // -----------------------------------------------------------------------
  156. // Helper class to lock&unlock a mutex during a function scope.
  157. template <class Mutex>
  158. class CarlaScopeLocker
  159. {
  160. public:
  161. CarlaScopeLocker(const Mutex& mutex) noexcept
  162. : fMutex(mutex)
  163. {
  164. fMutex.lock();
  165. }
  166. ~CarlaScopeLocker() noexcept
  167. {
  168. fMutex.unlock();
  169. }
  170. private:
  171. const Mutex& fMutex;
  172. CARLA_PREVENT_HEAP_ALLOCATION
  173. CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeLocker)
  174. };
  175. // -----------------------------------------------------------------------
  176. // Helper class to try-lock&unlock a mutex during a function scope.
  177. template <class Mutex>
  178. class CarlaScopeTryLocker
  179. {
  180. public:
  181. CarlaScopeTryLocker(const Mutex& mutex) noexcept
  182. : fMutex(mutex),
  183. fLocked(mutex.tryLock()) {}
  184. ~CarlaScopeTryLocker() noexcept
  185. {
  186. if (fLocked)
  187. fMutex.unlock();
  188. }
  189. private:
  190. const Mutex& fMutex;
  191. const bool fLocked;
  192. CARLA_PREVENT_HEAP_ALLOCATION
  193. CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeTryLocker)
  194. };
  195. // -----------------------------------------------------------------------
  196. // Helper class to unlock&lock a mutex during a function scope.
  197. template <class Mutex>
  198. class CarlaScopeUnlocker
  199. {
  200. public:
  201. CarlaScopeUnlocker(const Mutex& mutex) noexcept
  202. : fMutex(mutex)
  203. {
  204. fMutex.unlock();
  205. }
  206. ~CarlaScopeUnlocker() noexcept
  207. {
  208. fMutex.lock();
  209. }
  210. private:
  211. const Mutex& fMutex;
  212. CARLA_PREVENT_HEAP_ALLOCATION
  213. CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeUnlocker)
  214. };
  215. // -----------------------------------------------------------------------
  216. // Define types
  217. typedef CarlaScopeLocker<CarlaMutex> CarlaMutexLocker;
  218. typedef CarlaScopeLocker<CarlaRecursiveMutex> CarlaRecursiveMutexLocker;
  219. typedef CarlaScopeTryLocker<CarlaMutex> CarlaMutexTryLocker;
  220. typedef CarlaScopeTryLocker<CarlaRecursiveMutex> CarlaRecursiveMutexTryLocker;
  221. typedef CarlaScopeUnlocker<CarlaMutex> CarlaMutexUnlocker;
  222. typedef CarlaScopeUnlocker<CarlaRecursiveMutex> CarlaRecursiveMutexUnlocker;
  223. // -----------------------------------------------------------------------
  224. #endif // CARLA_MUTEX_HPP_INCLUDED