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.

255 lines
5.2KB

  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. /*
  76. * Helper class to lock&unlock a mutex during a function scope.
  77. */
  78. class ScopedLocker
  79. {
  80. public:
  81. ScopedLocker(CarlaMutex& mutex) noexcept
  82. : fMutex(mutex)
  83. {
  84. fMutex.lock();
  85. }
  86. ~ScopedLocker() noexcept
  87. {
  88. fMutex.unlock();
  89. }
  90. private:
  91. CarlaMutex& fMutex;
  92. CARLA_PREVENT_HEAP_ALLOCATION
  93. CARLA_DECLARE_NON_COPY_CLASS(ScopedLocker)
  94. };
  95. /*
  96. * Helper class to unlock&lock a mutex during a function scope.
  97. */
  98. class ScopedUnlocker
  99. {
  100. public:
  101. ScopedUnlocker(CarlaMutex& mutex) noexcept
  102. : fMutex(mutex)
  103. {
  104. fMutex.unlock();
  105. }
  106. ~ScopedUnlocker() noexcept
  107. {
  108. fMutex.lock();
  109. }
  110. private:
  111. CarlaMutex& fMutex;
  112. CARLA_PREVENT_HEAP_ALLOCATION
  113. CARLA_DECLARE_NON_COPY_CLASS(ScopedUnlocker)
  114. };
  115. private:
  116. mutable pthread_mutex_t fMutex; // The mutex
  117. mutable volatile bool fTryLockWasCalled; // true if "tryLock()" was called at least once
  118. CARLA_PREVENT_HEAP_ALLOCATION
  119. CARLA_DECLARE_NON_COPY_CLASS(CarlaMutex)
  120. };
  121. // -----------------------------------------------------------------------
  122. // CarlaCriticalSection class
  123. class CarlaCriticalSection
  124. {
  125. public:
  126. /*
  127. * Constructor.
  128. */
  129. CarlaCriticalSection() noexcept
  130. {
  131. #ifdef CARLA_OS_WIN
  132. InitializeCriticalSection(&fSection);
  133. #else
  134. fCounter = 0;
  135. fOwnerThread = 0;
  136. pthread_mutex_init(&fMutex, nullptr);
  137. #endif
  138. }
  139. /*
  140. * Destructor.
  141. */
  142. ~CarlaCriticalSection() noexcept
  143. {
  144. #ifdef CARLA_OS_WIN
  145. DeleteCriticalSection(&fSection);
  146. #else
  147. pthread_mutex_destroy(&fMutex);
  148. #endif
  149. }
  150. /*
  151. * Enter section.
  152. */
  153. void enter() noexcept
  154. {
  155. #ifdef CARLA_OS_WIN
  156. EnterCriticalSection(&fSection);
  157. #else
  158. const pthread_t thisThread(pthread_self());
  159. if (fOwnerThread == thisThread)
  160. {
  161. ++fCounter;
  162. }
  163. else
  164. {
  165. pthread_mutex_lock(&fMutex);
  166. fOwnerThread = thisThread;
  167. fCounter = 0;
  168. }
  169. #endif
  170. }
  171. /*
  172. * Leave section.
  173. */
  174. void leave() noexcept
  175. {
  176. #ifdef CARLA_OS_WIN
  177. LeaveCriticalSection(&fSection);
  178. #else
  179. if (--fCounter < 0)
  180. {
  181. fOwnerThread = 0;
  182. pthread_mutex_unlock(&fMutex);
  183. }
  184. #endif
  185. }
  186. /*
  187. * Helper class to enter&leave during a function scope.
  188. */
  189. class Scope
  190. {
  191. public:
  192. Scope(CarlaCriticalSection& cs) noexcept
  193. : fSection(cs)
  194. {
  195. fSection.enter();
  196. }
  197. ~Scope() noexcept
  198. {
  199. fSection.leave();
  200. }
  201. private:
  202. CarlaCriticalSection& fSection;
  203. CARLA_PREVENT_HEAP_ALLOCATION
  204. CARLA_DECLARE_NON_COPY_CLASS(Scope)
  205. };
  206. private:
  207. #ifdef CARLA_OS_WIN
  208. CRITICAL_SECTION fSection;
  209. #else
  210. int fCounter;
  211. pthread_t fOwnerThread;
  212. pthread_mutex_t fMutex;
  213. #endif
  214. CARLA_PREVENT_HEAP_ALLOCATION
  215. CARLA_DECLARE_NON_COPY_CLASS(CarlaCriticalSection)
  216. };
  217. // -----------------------------------------------------------------------
  218. #endif // CARLA_MUTEX_HPP_INCLUDED