| 
							- /*
 -  * Carla Mutex
 -  * Copyright (C) 2013-2022 Filipe Coelho <falktx@falktx.com>
 -  *
 -  * This program is free software; you can redistribute it and/or
 -  * modify it under the terms of the GNU General Public License as
 -  * published by the Free Software Foundation; either version 2 of
 -  * the License, or any later version.
 -  *
 -  * This program is distributed in the hope that it will be useful,
 -  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 -  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 -  * GNU General Public License for more details.
 -  *
 -  * For a full copy of the GNU General Public License see the doc/GPL.txt file.
 -  */
 - 
 - #ifndef CARLA_MUTEX_HPP_INCLUDED
 - #define CARLA_MUTEX_HPP_INCLUDED
 - 
 - #include "CarlaUtils.hpp"
 - 
 - #include <pthread.h>
 - 
 - class CarlaSignal;
 - 
 - // -----------------------------------------------------------------------
 - // CarlaMutex class
 - 
 - class CarlaMutex
 - {
 - public:
 -     /*
 -      * Constructor.
 -      */
 -     CarlaMutex(const bool inheritPriority = true) noexcept
 -         : fMutex(),
 -           fTryLockWasCalled(false)
 -     {
 -         pthread_mutexattr_t attr;
 -         pthread_mutexattr_init(&attr);
 -         pthread_mutexattr_setprotocol(&attr, inheritPriority ? PTHREAD_PRIO_INHERIT : PTHREAD_PRIO_NONE);
 -         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
 -         pthread_mutex_init(&fMutex, &attr);
 -         pthread_mutexattr_destroy(&attr);
 -     }
 - 
 -     /*
 -      * Destructor.
 -      */
 -     ~CarlaMutex() noexcept
 -     {
 -         pthread_mutex_destroy(&fMutex);
 -     }
 - 
 -     /*
 -      * Check if "tryLock()" was called before.
 -      */
 -     bool wasTryLockCalled() const noexcept
 -     {
 -         const bool ret(fTryLockWasCalled);
 -         fTryLockWasCalled = false;
 -         return ret;
 -     }
 - 
 -     /*
 -      * Lock the mutex.
 -      */
 -     bool lock() const noexcept
 -     {
 -         return (pthread_mutex_lock(&fMutex) == 0);
 -     }
 - 
 -     /*
 -      * Try to lock the mutex.
 -      * Returns true if successful.
 -      */
 -     bool tryLock() const noexcept
 -     {
 -         fTryLockWasCalled = true;
 - 
 -         return (pthread_mutex_trylock(&fMutex) == 0);
 -     }
 - 
 -     /*
 -      * Unlock the mutex, optionally resetting the tryLock check.
 -      */
 -     void unlock(const bool resetTryLock = false) const noexcept
 -     {
 -         if (resetTryLock)
 -             fTryLockWasCalled = false;
 - 
 -         pthread_mutex_unlock(&fMutex);
 -     }
 - 
 - private:
 -     mutable pthread_mutex_t fMutex;
 -     mutable volatile bool fTryLockWasCalled; // true if "tryLock()" was called at least once
 - 
 -     CARLA_DECLARE_NON_COPYABLE(CarlaMutex)
 - };
 - 
 - // -----------------------------------------------------------------------
 - // CarlaRecursiveMutex class
 - 
 - class CarlaRecursiveMutex
 - {
 - public:
 -     /*
 -      * Constructor.
 -      */
 -     CarlaRecursiveMutex() noexcept
 - #ifdef CARLA_OS_WIN
 -         : fSection()
 - #else
 -         : fMutex()
 - #endif
 -     {
 - #ifdef CARLA_OS_WIN
 -         InitializeCriticalSection(&fSection);
 - #else
 -         pthread_mutexattr_t attr;
 -         pthread_mutexattr_init(&attr);
 -         pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
 -         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 -         pthread_mutex_init(&fMutex, &attr);
 -         pthread_mutexattr_destroy(&attr);
 - #endif
 -     }
 - 
 -     /*
 -      * Destructor.
 -      */
 -     ~CarlaRecursiveMutex() noexcept
 -     {
 - #ifdef CARLA_OS_WIN
 -         DeleteCriticalSection(&fSection);
 - #else
 -         pthread_mutex_destroy(&fMutex);
 - #endif
 -     }
 - 
 -     /*
 -      * Lock the mutex.
 -      */
 -     bool lock() const noexcept
 -     {
 - #ifdef CARLA_OS_WIN
 -         EnterCriticalSection(&fSection);
 -         return true;
 - #else
 -         return (pthread_mutex_lock(&fMutex) == 0);
 - #endif
 -     }
 - 
 -     /*
 -      * Try to lock the mutex.
 -      * Returns true if successful.
 -      */
 -     bool tryLock() const noexcept
 -     {
 - #ifdef CARLA_OS_WIN
 -         return (TryEnterCriticalSection(&fSection) != FALSE);
 - #else
 -         return (pthread_mutex_trylock(&fMutex) == 0);
 - #endif
 -     }
 - 
 -     /*
 -      * Unlock the mutex.
 -      */
 -     void unlock() const noexcept
 -     {
 - #ifdef CARLA_OS_WIN
 -         LeaveCriticalSection(&fSection);
 - #else
 -         pthread_mutex_unlock(&fMutex);
 - #endif
 -     }
 - 
 - private:
 - #ifdef CARLA_OS_WIN
 -     mutable CRITICAL_SECTION fSection;
 - #else
 -     mutable pthread_mutex_t fMutex;
 - #endif
 - 
 -     CARLA_DECLARE_NON_COPYABLE(CarlaRecursiveMutex)
 - };
 - 
 - // -----------------------------------------------------------------------
 - // CarlaSignal class
 - 
 - class CarlaSignal
 - {
 - public:
 -     /*
 -      * Constructor.
 -      */
 -     CarlaSignal() noexcept
 -         : fCondition(),
 -           fMutex(),
 -           fTriggered(false)
 -     {
 -         pthread_condattr_t cattr;
 -         pthread_condattr_init(&cattr);
 -         pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_PRIVATE);
 -         pthread_cond_init(&fCondition, &cattr);
 -         pthread_condattr_destroy(&cattr);
 - 
 -         pthread_mutexattr_t mattr;
 -         pthread_mutexattr_init(&mattr);
 -         pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
 -         pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_NORMAL);
 -         pthread_mutex_init(&fMutex, &mattr);
 -         pthread_mutexattr_destroy(&mattr);
 -     }
 - 
 -     /*
 -      * Destructor.
 -      */
 -     ~CarlaSignal() noexcept
 -     {
 -         pthread_cond_destroy(&fCondition);
 -         pthread_mutex_destroy(&fMutex);
 -     }
 - 
 -     /*
 -      * Wait for a signal.
 -      */
 -     void wait() noexcept
 -     {
 -         pthread_mutex_lock(&fMutex);
 - 
 -         while (! fTriggered)
 -         {
 -             try {
 -                 pthread_cond_wait(&fCondition, &fMutex);
 -             } CARLA_SAFE_EXCEPTION("pthread_cond_wait");
 -         }
 - 
 -         fTriggered = false;
 - 
 -         pthread_mutex_unlock(&fMutex);
 -     }
 - 
 -     /*
 -      * Wake up all waiting threads.
 -      */
 -     void signal() noexcept
 -     {
 -         pthread_mutex_lock(&fMutex);
 - 
 -         if (! fTriggered)
 -         {
 -             fTriggered = true;
 -             pthread_cond_broadcast(&fCondition);
 -         }
 - 
 -         pthread_mutex_unlock(&fMutex);
 -     }
 - 
 - private:
 -     pthread_cond_t  fCondition;
 -     pthread_mutex_t fMutex;
 -     volatile bool   fTriggered;
 - 
 -     CARLA_PREVENT_HEAP_ALLOCATION
 -     CARLA_DECLARE_NON_COPYABLE(CarlaSignal)
 - };
 - 
 - // -----------------------------------------------------------------------
 - // Helper class to lock&unlock a mutex during a function scope.
 - 
 - template <class Mutex>
 - class CarlaScopeLocker
 - {
 - public:
 -     CarlaScopeLocker(const Mutex& mutex) noexcept
 -         : fMutex(mutex)
 -     {
 -         fMutex.lock();
 -     }
 - 
 -     ~CarlaScopeLocker() noexcept
 -     {
 -         fMutex.unlock();
 -     }
 - 
 - private:
 -     const Mutex& fMutex;
 - 
 -     CARLA_PREVENT_HEAP_ALLOCATION
 -     CARLA_DECLARE_NON_COPYABLE(CarlaScopeLocker)
 - };
 - 
 - // -----------------------------------------------------------------------
 - // Helper class to try-lock&unlock a mutex during a function scope.
 - 
 - template <class Mutex>
 - class CarlaScopeTryLocker
 - {
 - public:
 -     CarlaScopeTryLocker(const Mutex& mutex) noexcept
 -         : fMutex(mutex),
 -           fLocked(mutex.tryLock()) {}
 - 
 -     CarlaScopeTryLocker(const Mutex& mutex, const bool forceLock) noexcept
 -         : fMutex(mutex),
 -           fLocked(forceLock ? mutex.lock() : mutex.tryLock()) {}
 - 
 -     ~CarlaScopeTryLocker() noexcept
 -     {
 -         if (fLocked)
 -             fMutex.unlock();
 -     }
 - 
 -     bool wasLocked() const noexcept
 -     {
 -         return fLocked;
 -     }
 - 
 -     bool wasNotLocked() const noexcept
 -     {
 -         return !fLocked;
 -     }
 - 
 -     bool tryAgain() const noexcept
 -     {
 -         return fMutex.tryLock();
 -     }
 - 
 - private:
 -     const Mutex& fMutex;
 -     const bool   fLocked;
 - 
 -     CARLA_PREVENT_HEAP_ALLOCATION
 -     CARLA_DECLARE_NON_COPYABLE(CarlaScopeTryLocker)
 - };
 - 
 - // -----------------------------------------------------------------------
 - // Helper class to unlock&lock a mutex during a function scope.
 - 
 - template <class Mutex>
 - class CarlaScopeUnlocker
 - {
 - public:
 -     CarlaScopeUnlocker(const Mutex& mutex) noexcept
 -         : fMutex(mutex)
 -     {
 -         fMutex.unlock();
 -     }
 - 
 -     ~CarlaScopeUnlocker() noexcept
 -     {
 -         fMutex.lock();
 -     }
 - 
 - private:
 -     const Mutex& fMutex;
 - 
 -     CARLA_PREVENT_HEAP_ALLOCATION
 -     CARLA_DECLARE_NON_COPYABLE(CarlaScopeUnlocker)
 - };
 - 
 - // -----------------------------------------------------------------------
 - // Define types
 - 
 - typedef CarlaScopeLocker<CarlaMutex>          CarlaMutexLocker;
 - typedef CarlaScopeLocker<CarlaRecursiveMutex> CarlaRecursiveMutexLocker;
 - 
 - typedef CarlaScopeTryLocker<CarlaMutex>          CarlaMutexTryLocker;
 - typedef CarlaScopeTryLocker<CarlaRecursiveMutex> CarlaRecursiveMutexTryLocker;
 - 
 - typedef CarlaScopeUnlocker<CarlaMutex>          CarlaMutexUnlocker;
 - typedef CarlaScopeUnlocker<CarlaRecursiveMutex> CarlaRecursiveMutexUnlocker;
 - 
 - // -----------------------------------------------------------------------
 - 
 - #endif // CARLA_MUTEX_HPP_INCLUDED
 
 
  |