VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / utils / CarlaMutex.hpp
blob71d9293826c887fc5e8115e09c7919d7edd20a36
1 /*
2 * Carla Mutex
3 * Copyright (C) 2013-2023 Filipe Coelho <falktx@falktx.com>
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.
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.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_MUTEX_HPP_INCLUDED
19 #define CARLA_MUTEX_HPP_INCLUDED
21 #include "CarlaUtils.hpp"
23 #include <pthread.h>
25 class CarlaSignal;
27 // -----------------------------------------------------------------------
28 // CarlaMutex class
30 class CARLA_API CarlaMutex
32 public:
34 * Constructor.
36 CarlaMutex(const bool inheritPriority = true) noexcept
37 : fMutex(),
38 fTryLockWasCalled(false)
40 pthread_mutexattr_t attr;
41 pthread_mutexattr_init(&attr);
42 #ifndef PTW32_DLLPORT
43 pthread_mutexattr_setprotocol(&attr, inheritPriority ? PTHREAD_PRIO_INHERIT : PTHREAD_PRIO_NONE);
44 #else
45 // unsupported?
46 (void)inheritPriority;
47 #endif
48 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
49 pthread_mutex_init(&fMutex, &attr);
50 pthread_mutexattr_destroy(&attr);
54 * Destructor.
56 ~CarlaMutex() noexcept
58 pthread_mutex_destroy(&fMutex);
62 * Check if "tryLock()" was called before.
64 bool wasTryLockCalled() const noexcept
66 const bool ret(fTryLockWasCalled);
67 fTryLockWasCalled = false;
68 return ret;
72 * Lock the mutex.
74 bool lock() const noexcept
76 return (pthread_mutex_lock(&fMutex) == 0);
80 * Try to lock the mutex.
81 * Returns true if successful.
83 bool tryLock() const noexcept
85 fTryLockWasCalled = true;
87 return (pthread_mutex_trylock(&fMutex) == 0);
91 * Unlock the mutex, optionally resetting the tryLock check.
93 void unlock(const bool resetTryLock = false) const noexcept
95 if (resetTryLock)
96 fTryLockWasCalled = false;
98 pthread_mutex_unlock(&fMutex);
101 private:
102 mutable pthread_mutex_t fMutex;
103 mutable volatile bool fTryLockWasCalled; // true if "tryLock()" was called at least once
105 CARLA_DECLARE_NON_COPYABLE(CarlaMutex)
108 // -----------------------------------------------------------------------
109 // CarlaRecursiveMutex class
111 class CarlaRecursiveMutex
113 public:
115 * Constructor.
117 CarlaRecursiveMutex() noexcept
118 #ifdef CARLA_OS_WIN
119 : fSection()
120 #else
121 : fMutex()
122 #endif
124 #ifdef CARLA_OS_WIN
125 InitializeCriticalSection(&fSection);
126 #else
127 pthread_mutexattr_t attr;
128 pthread_mutexattr_init(&attr);
129 pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
130 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
131 pthread_mutex_init(&fMutex, &attr);
132 pthread_mutexattr_destroy(&attr);
133 #endif
137 * Destructor.
139 ~CarlaRecursiveMutex() noexcept
141 #ifdef CARLA_OS_WIN
142 DeleteCriticalSection(&fSection);
143 #else
144 pthread_mutex_destroy(&fMutex);
145 #endif
149 * Lock the mutex.
151 bool lock() const noexcept
153 #ifdef CARLA_OS_WIN
154 EnterCriticalSection(&fSection);
155 return true;
156 #else
157 return (pthread_mutex_lock(&fMutex) == 0);
158 #endif
162 * Try to lock the mutex.
163 * Returns true if successful.
165 bool tryLock() const noexcept
167 #ifdef CARLA_OS_WIN
168 return (TryEnterCriticalSection(&fSection) != FALSE);
169 #else
170 return (pthread_mutex_trylock(&fMutex) == 0);
171 #endif
175 * Unlock the mutex.
177 void unlock() const noexcept
179 #ifdef CARLA_OS_WIN
180 LeaveCriticalSection(&fSection);
181 #else
182 pthread_mutex_unlock(&fMutex);
183 #endif
186 private:
187 #ifdef CARLA_OS_WIN
188 mutable CRITICAL_SECTION fSection;
189 #else
190 mutable pthread_mutex_t fMutex;
191 #endif
193 CARLA_DECLARE_NON_COPYABLE(CarlaRecursiveMutex)
196 // -----------------------------------------------------------------------
197 // CarlaSignal class
199 class CarlaSignal
201 public:
203 * Constructor.
205 CarlaSignal() noexcept
206 : fCondition(),
207 fMutex(),
208 fTriggered(false)
210 pthread_condattr_t cattr;
211 pthread_condattr_init(&cattr);
212 pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_PRIVATE);
213 pthread_cond_init(&fCondition, &cattr);
214 pthread_condattr_destroy(&cattr);
216 pthread_mutexattr_t mattr;
217 pthread_mutexattr_init(&mattr);
218 #ifndef PTW32_DLLPORT
219 pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
220 #endif
221 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_NORMAL);
222 pthread_mutex_init(&fMutex, &mattr);
223 pthread_mutexattr_destroy(&mattr);
227 * Destructor.
229 ~CarlaSignal() noexcept
231 pthread_cond_destroy(&fCondition);
232 pthread_mutex_destroy(&fMutex);
236 * Wait for a signal.
238 void wait() noexcept
240 pthread_mutex_lock(&fMutex);
242 while (! fTriggered)
244 try {
245 pthread_cond_wait(&fCondition, &fMutex);
246 } CARLA_SAFE_EXCEPTION("pthread_cond_wait");
249 fTriggered = false;
251 pthread_mutex_unlock(&fMutex);
255 * Wake up all waiting threads.
257 void signal() noexcept
259 pthread_mutex_lock(&fMutex);
261 if (! fTriggered)
263 fTriggered = true;
264 pthread_cond_broadcast(&fCondition);
267 pthread_mutex_unlock(&fMutex);
270 private:
271 pthread_cond_t fCondition;
272 pthread_mutex_t fMutex;
273 volatile bool fTriggered;
275 CARLA_PREVENT_HEAP_ALLOCATION
276 CARLA_DECLARE_NON_COPYABLE(CarlaSignal)
279 // -----------------------------------------------------------------------
280 // Helper class to lock&unlock a mutex during a function scope.
282 template <class Mutex>
283 class CarlaScopeLocker
285 public:
286 CarlaScopeLocker(const Mutex& mutex) noexcept
287 : fMutex(mutex)
289 fMutex.lock();
292 ~CarlaScopeLocker() noexcept
294 fMutex.unlock();
297 private:
298 const Mutex& fMutex;
300 CARLA_PREVENT_HEAP_ALLOCATION
301 CARLA_DECLARE_NON_COPYABLE(CarlaScopeLocker)
304 // -----------------------------------------------------------------------
305 // Helper class to try-lock&unlock a mutex during a function scope.
307 template <class Mutex>
308 class CarlaScopeTryLocker
310 public:
311 CarlaScopeTryLocker(const Mutex& mutex) noexcept
312 : fMutex(mutex),
313 fLocked(mutex.tryLock()) {}
315 CarlaScopeTryLocker(const Mutex& mutex, const bool forceLock) noexcept
316 : fMutex(mutex),
317 fLocked(forceLock ? mutex.lock() : mutex.tryLock()) {}
319 ~CarlaScopeTryLocker() noexcept
321 if (fLocked)
322 fMutex.unlock();
325 bool wasLocked() const noexcept
327 return fLocked;
330 bool wasNotLocked() const noexcept
332 return !fLocked;
335 bool tryAgain() const noexcept
337 return fMutex.tryLock();
340 private:
341 const Mutex& fMutex;
342 const bool fLocked;
344 CARLA_PREVENT_HEAP_ALLOCATION
345 CARLA_DECLARE_NON_COPYABLE(CarlaScopeTryLocker)
348 // -----------------------------------------------------------------------
349 // Helper class to unlock&lock a mutex during a function scope.
351 template <class Mutex>
352 class CarlaScopeUnlocker
354 public:
355 CarlaScopeUnlocker(const Mutex& mutex) noexcept
356 : fMutex(mutex)
358 fMutex.unlock();
361 ~CarlaScopeUnlocker() noexcept
363 fMutex.lock();
366 private:
367 const Mutex& fMutex;
369 CARLA_PREVENT_HEAP_ALLOCATION
370 CARLA_DECLARE_NON_COPYABLE(CarlaScopeUnlocker)
373 // -----------------------------------------------------------------------
374 // Define types
376 typedef CarlaScopeLocker<CarlaMutex> CarlaMutexLocker;
377 typedef CarlaScopeLocker<CarlaRecursiveMutex> CarlaRecursiveMutexLocker;
379 typedef CarlaScopeTryLocker<CarlaMutex> CarlaMutexTryLocker;
380 typedef CarlaScopeTryLocker<CarlaRecursiveMutex> CarlaRecursiveMutexTryLocker;
382 typedef CarlaScopeUnlocker<CarlaMutex> CarlaMutexUnlocker;
383 typedef CarlaScopeUnlocker<CarlaRecursiveMutex> CarlaRecursiveMutexUnlocker;
385 // -----------------------------------------------------------------------
387 #endif // CARLA_MUTEX_HPP_INCLUDED