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.

330 lines
7.0KB

  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. #if 0 //def CARLA_OS_WIN
  31. : fAlreadyLocked(false),
  32. fSection(),
  33. #else
  34. : fMutex(),
  35. #endif
  36. fTryLockWasCalled(false)
  37. {
  38. #if 0 //def CARLA_OS_WIN
  39. InitializeCriticalSection(&fSection);
  40. #else
  41. pthread_mutex_init(&fMutex, nullptr);
  42. #endif
  43. }
  44. /*
  45. * Destructor.
  46. */
  47. ~CarlaMutex() noexcept
  48. {
  49. #if 0 //def CARLA_OS_WIN
  50. DeleteCriticalSection(&fSection);
  51. #else
  52. pthread_mutex_destroy(&fMutex);
  53. #endif
  54. }
  55. /*
  56. * Check if "tryLock()" was called before.
  57. */
  58. bool wasTryLockCalled() const noexcept
  59. {
  60. const bool ret(fTryLockWasCalled);
  61. fTryLockWasCalled = false;
  62. return ret;
  63. }
  64. /*
  65. * Lock the mutex.
  66. */
  67. void lock() const noexcept
  68. {
  69. #if 0 //def CARLA_OS_WIN
  70. EnterCriticalSection(&fSection);
  71. for (;fAlreadyLocked;)
  72. Sleep(500);
  73. fAlreadyLocked = true;
  74. #else
  75. pthread_mutex_lock(&fMutex);
  76. #endif
  77. }
  78. /*
  79. * Try to lock the mutex.
  80. * Returns true if successful.
  81. */
  82. bool tryLock() const noexcept
  83. {
  84. fTryLockWasCalled = true;
  85. #if 0 //def CARLA_OS_WIN
  86. if (TryEnterCriticalSection(&fSection) == FALSE)
  87. return false;
  88. if (fAlreadyLocked)
  89. {
  90. LeaveCriticalSection(&fSection);
  91. return false;
  92. }
  93. fAlreadyLocked = true;
  94. return true;
  95. #else
  96. return (pthread_mutex_trylock(&fMutex) == 0);
  97. #endif
  98. }
  99. /*
  100. * Unlock the mutex, optionally resetting the tryLock check.
  101. */
  102. void unlock(const bool resetTryLock = false) const noexcept
  103. {
  104. if (resetTryLock)
  105. fTryLockWasCalled = false;
  106. #if 0 //def CARLA_OS_WIN
  107. fAlreadyLocked = false;
  108. LeaveCriticalSection(&fSection);
  109. #else
  110. pthread_mutex_unlock(&fMutex);
  111. #endif
  112. }
  113. private:
  114. #if 0 //def CARLA_OS_WIN
  115. mutable volatile bool fAlreadyLocked;
  116. mutable CRITICAL_SECTION fSection;
  117. #else
  118. mutable pthread_mutex_t fMutex;
  119. #endif
  120. mutable volatile bool fTryLockWasCalled; // true if "tryLock()" was called at least once
  121. CARLA_PREVENT_HEAP_ALLOCATION
  122. CARLA_DECLARE_NON_COPY_CLASS(CarlaMutex)
  123. };
  124. // -----------------------------------------------------------------------
  125. // CarlaRecursiveMutex class
  126. class CarlaRecursiveMutex
  127. {
  128. public:
  129. /*
  130. * Constructor.
  131. */
  132. CarlaRecursiveMutex() noexcept
  133. #ifdef CARLA_OS_WIN
  134. : fSection()
  135. #else
  136. : fMutex()
  137. #endif
  138. {
  139. #ifdef CARLA_OS_WIN
  140. InitializeCriticalSection(&fSection);
  141. #else
  142. pthread_mutexattr_t atts;
  143. pthread_mutexattr_init(&atts);
  144. pthread_mutexattr_settype(&atts, PTHREAD_MUTEX_RECURSIVE);
  145. pthread_mutex_init(&fMutex, &atts);
  146. pthread_mutexattr_destroy(&atts);
  147. #endif
  148. }
  149. /*
  150. * Destructor.
  151. */
  152. ~CarlaRecursiveMutex() noexcept
  153. {
  154. #ifdef CARLA_OS_WIN
  155. DeleteCriticalSection(&fSection);
  156. #else
  157. pthread_mutex_destroy(&fMutex);
  158. #endif
  159. }
  160. /*
  161. * Lock the mutex.
  162. */
  163. void lock() const noexcept
  164. {
  165. #ifdef CARLA_OS_WIN
  166. EnterCriticalSection(&fSection);
  167. #else
  168. pthread_mutex_lock(&fMutex);
  169. #endif
  170. }
  171. /*
  172. * Try to lock the mutex.
  173. * Returns true if successful.
  174. */
  175. bool tryLock() const noexcept
  176. {
  177. #ifdef CARLA_OS_WIN
  178. return (TryEnterCriticalSection(&fSection) != FALSE);
  179. #else
  180. return (pthread_mutex_trylock(&fMutex) == 0);
  181. #endif
  182. }
  183. /*
  184. * Unlock the mutex.
  185. */
  186. void unlock() const noexcept
  187. {
  188. #ifdef CARLA_OS_WIN
  189. LeaveCriticalSection(&fSection);
  190. #else
  191. pthread_mutex_unlock(&fMutex);
  192. #endif
  193. }
  194. private:
  195. #ifdef CARLA_OS_WIN
  196. mutable CRITICAL_SECTION fSection;
  197. #else
  198. mutable pthread_mutex_t fMutex;
  199. #endif
  200. CARLA_PREVENT_HEAP_ALLOCATION
  201. CARLA_DECLARE_NON_COPY_CLASS(CarlaRecursiveMutex)
  202. };
  203. // -----------------------------------------------------------------------
  204. // Helper class to lock&unlock a mutex during a function scope.
  205. template <class Mutex>
  206. class CarlaScopeLocker
  207. {
  208. public:
  209. CarlaScopeLocker(const Mutex& mutex) noexcept
  210. : fMutex(mutex)
  211. {
  212. fMutex.lock();
  213. }
  214. ~CarlaScopeLocker() noexcept
  215. {
  216. fMutex.unlock();
  217. }
  218. private:
  219. const Mutex& fMutex;
  220. CARLA_PREVENT_HEAP_ALLOCATION
  221. CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeLocker)
  222. };
  223. // -----------------------------------------------------------------------
  224. // Helper class to try-lock&unlock a mutex during a function scope.
  225. template <class Mutex>
  226. class CarlaScopeTryLocker
  227. {
  228. public:
  229. CarlaScopeTryLocker(const Mutex& mutex) noexcept
  230. : fMutex(mutex),
  231. fLocked(mutex.tryLock()) {}
  232. ~CarlaScopeTryLocker() noexcept
  233. {
  234. if (fLocked)
  235. fMutex.unlock();
  236. }
  237. bool wasLocked() const noexcept
  238. {
  239. return fLocked;
  240. }
  241. bool wasNotLocked() const noexcept
  242. {
  243. return !fLocked;
  244. }
  245. private:
  246. const Mutex& fMutex;
  247. const bool fLocked;
  248. CARLA_PREVENT_HEAP_ALLOCATION
  249. CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeTryLocker)
  250. };
  251. // -----------------------------------------------------------------------
  252. // Helper class to unlock&lock a mutex during a function scope.
  253. template <class Mutex>
  254. class CarlaScopeUnlocker
  255. {
  256. public:
  257. CarlaScopeUnlocker(const Mutex& mutex) noexcept
  258. : fMutex(mutex)
  259. {
  260. fMutex.unlock();
  261. }
  262. ~CarlaScopeUnlocker() noexcept
  263. {
  264. fMutex.lock();
  265. }
  266. private:
  267. const Mutex& fMutex;
  268. CARLA_PREVENT_HEAP_ALLOCATION
  269. CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeUnlocker)
  270. };
  271. // -----------------------------------------------------------------------
  272. // Define types
  273. typedef CarlaScopeLocker<CarlaMutex> CarlaMutexLocker;
  274. typedef CarlaScopeLocker<CarlaRecursiveMutex> CarlaRecursiveMutexLocker;
  275. typedef CarlaScopeTryLocker<CarlaMutex> CarlaMutexTryLocker;
  276. typedef CarlaScopeTryLocker<CarlaRecursiveMutex> CarlaRecursiveMutexTryLocker;
  277. typedef CarlaScopeUnlocker<CarlaMutex> CarlaMutexUnlocker;
  278. typedef CarlaScopeUnlocker<CarlaRecursiveMutex> CarlaRecursiveMutexUnlocker;
  279. // -----------------------------------------------------------------------
  280. #endif // CARLA_MUTEX_HPP_INCLUDED