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"
27 // -----------------------------------------------------------------------
30 class CARLA_API CarlaMutex
36 CarlaMutex(const bool inheritPriority
= true) noexcept
38 fTryLockWasCalled(false)
40 pthread_mutexattr_t attr
;
41 pthread_mutexattr_init(&attr
);
43 pthread_mutexattr_setprotocol(&attr
, inheritPriority
? PTHREAD_PRIO_INHERIT
: PTHREAD_PRIO_NONE
);
46 (void)inheritPriority
;
48 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_NORMAL
);
49 pthread_mutex_init(&fMutex
, &attr
);
50 pthread_mutexattr_destroy(&attr
);
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;
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
96 fTryLockWasCalled
= false;
98 pthread_mutex_unlock(&fMutex
);
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
117 CarlaRecursiveMutex() noexcept
125 InitializeCriticalSection(&fSection
);
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
);
139 ~CarlaRecursiveMutex() noexcept
142 DeleteCriticalSection(&fSection
);
144 pthread_mutex_destroy(&fMutex
);
151 bool lock() const noexcept
154 EnterCriticalSection(&fSection
);
157 return (pthread_mutex_lock(&fMutex
) == 0);
162 * Try to lock the mutex.
163 * Returns true if successful.
165 bool tryLock() const noexcept
168 return (TryEnterCriticalSection(&fSection
) != FALSE
);
170 return (pthread_mutex_trylock(&fMutex
) == 0);
177 void unlock() const noexcept
180 LeaveCriticalSection(&fSection
);
182 pthread_mutex_unlock(&fMutex
);
188 mutable CRITICAL_SECTION fSection
;
190 mutable pthread_mutex_t fMutex
;
193 CARLA_DECLARE_NON_COPYABLE(CarlaRecursiveMutex
)
196 // -----------------------------------------------------------------------
205 CarlaSignal() noexcept
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
);
221 pthread_mutexattr_settype(&mattr
, PTHREAD_MUTEX_NORMAL
);
222 pthread_mutex_init(&fMutex
, &mattr
);
223 pthread_mutexattr_destroy(&mattr
);
229 ~CarlaSignal() noexcept
231 pthread_cond_destroy(&fCondition
);
232 pthread_mutex_destroy(&fMutex
);
240 pthread_mutex_lock(&fMutex
);
245 pthread_cond_wait(&fCondition
, &fMutex
);
246 } CARLA_SAFE_EXCEPTION("pthread_cond_wait");
251 pthread_mutex_unlock(&fMutex
);
255 * Wake up all waiting threads.
257 void signal() noexcept
259 pthread_mutex_lock(&fMutex
);
264 pthread_cond_broadcast(&fCondition
);
267 pthread_mutex_unlock(&fMutex
);
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
286 CarlaScopeLocker(const Mutex
& mutex
) noexcept
292 ~CarlaScopeLocker() noexcept
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
311 CarlaScopeTryLocker(const Mutex
& mutex
) noexcept
313 fLocked(mutex
.tryLock()) {}
315 CarlaScopeTryLocker(const Mutex
& mutex
, const bool forceLock
) noexcept
317 fLocked(forceLock
? mutex
.lock() : mutex
.tryLock()) {}
319 ~CarlaScopeTryLocker() noexcept
325 bool wasLocked() const noexcept
330 bool wasNotLocked() const noexcept
335 bool tryAgain() const noexcept
337 return fMutex
.tryLock();
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
355 CarlaScopeUnlocker(const Mutex
& mutex
) noexcept
361 ~CarlaScopeUnlocker() noexcept
369 CARLA_PREVENT_HEAP_ALLOCATION
370 CARLA_DECLARE_NON_COPYABLE(CarlaScopeUnlocker
)
373 // -----------------------------------------------------------------------
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