diff --git a/source/backend/engine/CarlaEngineInternal.cpp b/source/backend/engine/CarlaEngineInternal.cpp index dfc00e202..283ac620d 100644 --- a/source/backend/engine/CarlaEngineInternal.cpp +++ b/source/backend/engine/CarlaEngineInternal.cpp @@ -864,7 +864,7 @@ void CarlaEngineProtectedData::processRackFull(float** const inBuf, const uint32 { EngineRackBuffers* const rack(bufAudio.rack); - const CarlaCriticalSection::Scope _cs2(rack->connectLock); + const CarlaCriticalSectionScope _cs2(rack->connectLock); // connect input buffers if (rack->connectedIn1.count() == 0) diff --git a/source/backend/plugin/BridgePlugin.cpp b/source/backend/plugin/BridgePlugin.cpp index c28952ccc..1e3258c1f 100644 --- a/source/backend/plugin/BridgePlugin.cpp +++ b/source/backend/plugin/BridgePlugin.cpp @@ -520,7 +520,7 @@ public: const float fixedValue(pData->param.getFixedValue(parameterId, value)); fParams[parameterId].value = fixedValue; - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); fShmControl.writeOpcode(kPluginBridgeOpcodeSetParameter); fShmControl.writeInt(static_cast(parameterId)); @@ -534,7 +534,7 @@ public: { CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->prog.count),); - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); fShmControl.writeOpcode(kPluginBridgeOpcodeSetProgram); fShmControl.writeInt(index); @@ -547,7 +547,7 @@ public: { CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast(pData->midiprog.count),); - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); fShmControl.writeOpcode(kPluginBridgeOpcodeSetMidiProgram); fShmControl.writeInt(index); @@ -769,7 +769,7 @@ public: void activate() noexcept override { { - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); fShmControl.writeOpcode(kPluginBridgeOpcodeSetParameter); fShmControl.writeInt(PARAMETER_ACTIVE); @@ -790,7 +790,7 @@ public: void deactivate() noexcept override { { - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); fShmControl.writeOpcode(kPluginBridgeOpcodeSetParameter); fShmControl.writeInt(PARAMETER_ACTIVE); @@ -852,7 +852,7 @@ public: data2 = static_cast(note.note); data3 = static_cast(note.velo); - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); fShmControl.writeOpcode(kPluginBridgeOpcodeMidiEvent); fShmControl.writeLong(0); @@ -988,7 +988,7 @@ public: if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F) { - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); fShmControl.writeOpcode(kPluginBridgeOpcodeMidiEvent); fShmControl.writeLong(event.time); @@ -1083,7 +1083,7 @@ public: data[j] = static_cast(midiEvent.data[j]); { - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); fShmControl.writeOpcode(kPluginBridgeOpcodeMidiEvent); fShmControl.writeLong(event.time); @@ -1176,7 +1176,7 @@ public: // Run plugin { - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); fShmControl.writeOpcode(kPluginBridgeOpcodeProcess); fShmControl.commitWrite(); @@ -1263,7 +1263,7 @@ public: void bufferSizeChanged(const uint32_t newBufferSize) override { - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); resizeAudioPool(newBufferSize); @@ -1274,7 +1274,7 @@ public: void sampleRateChanged(const double newSampleRate) override { - const CarlaCriticalSection::Scope _cs(fShmControl.lock); + const CarlaCriticalSectionScope _cs(fShmControl.lock); fShmControl.writeOpcode(kPluginBridgeOpcodeSetSampleRate); fShmControl.writeFloat(static_cast(newSampleRate)); @@ -1910,7 +1910,7 @@ public: // init OSC { - char shmIdStr[16+1] = { 0 }; + char shmIdStr[18+1] = { 0 }; std::strncpy(shmIdStr, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6); std::strncat(shmIdStr, &fShmControl.filename[fShmControl.filename.length()-6], 6); std::strncat(shmIdStr, &fShmTime.filename[fShmTime.filename.length()-6], 6); diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 1f06717e0..7bec0fa3e 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -1761,7 +1761,7 @@ void CarlaPlugin::sendMidiAllNotesOffToCallback() void CarlaPlugin::postRtEventsRun() { - const CarlaMutex::ScopedLocker sl(pData->postRtEvents.mutex); + const CarlaMutexLocker sl(pData->postRtEvents.mutex); #ifndef BUILD_BRIDGE const bool sendOsc(pData->engine->isOscControlRegistered()); #endif diff --git a/source/modules/native-plugins/audio-base.hpp b/source/modules/native-plugins/audio-base.hpp index 651b65832..2b3d97092 100644 --- a/source/modules/native-plugins/audio-base.hpp +++ b/source/modules/native-plugins/audio-base.hpp @@ -148,7 +148,7 @@ public: fNeedsRead = false; stopThread(1000); - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker sl(fMutex); fPool.reset(); } @@ -279,7 +279,7 @@ public: i = j = 0; // lock, and put data asap - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker sl(fMutex); for (ssize_t size = (ssize_t)fPool.size; i < size && j < rv; ++j) { diff --git a/source/modules/native-plugins/midi-base.hpp b/source/modules/native-plugins/midi-base.hpp index 0a5f77b1a..f7fa42948 100644 --- a/source/modules/native-plugins/midi-base.hpp +++ b/source/modules/native-plugins/midi-base.hpp @@ -193,7 +193,7 @@ public: void clear() { - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker sl(fMutex); fData.clear(); } @@ -210,7 +210,7 @@ private: { if (fData.isEmpty()) { - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker sl(fMutex); fData.append(event); return; } @@ -222,12 +222,12 @@ private: if (event->time >= oldEvent->time) continue; - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker sl(fMutex); fData.insertAt(event, it); return; } - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker sl(fMutex); fData.append(event); } }; diff --git a/source/utils/CarlaLibCounter.hpp b/source/utils/CarlaLibCounter.hpp index 057114bef..981cb541b 100644 --- a/source/utils/CarlaLibCounter.hpp +++ b/source/utils/CarlaLibCounter.hpp @@ -33,7 +33,7 @@ public: { CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker sl(fMutex); for (LinkedList::Itenerator it = fLibs.begin(); it.valid(); it.next()) { @@ -67,7 +67,7 @@ public: { CARLA_SAFE_ASSERT_RETURN(libPtr != nullptr, false); - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker sl(fMutex); for (LinkedList::Itenerator it = fLibs.begin(); it.valid(); it.next()) { diff --git a/source/utils/CarlaMutex.hpp b/source/utils/CarlaMutex.hpp index aa15e061e..99acfe360 100644 --- a/source/utils/CarlaMutex.hpp +++ b/source/utils/CarlaMutex.hpp @@ -85,54 +85,6 @@ public: pthread_mutex_unlock(&fMutex); } - /* - * Helper class to lock&unlock a mutex during a function scope. - */ - class ScopedLocker - { - public: - ScopedLocker(CarlaMutex& mutex) noexcept - : fMutex(mutex) - { - fMutex.lock(); - } - - ~ScopedLocker() noexcept - { - fMutex.unlock(); - } - - private: - CarlaMutex& fMutex; - - CARLA_PREVENT_HEAP_ALLOCATION - CARLA_DECLARE_NON_COPY_CLASS(ScopedLocker) - }; - - /* - * Helper class to unlock&lock a mutex during a function scope. - */ - class ScopedUnlocker - { - public: - ScopedUnlocker(CarlaMutex& mutex) noexcept - : fMutex(mutex) - { - fMutex.unlock(); - } - - ~ScopedUnlocker() noexcept - { - fMutex.lock(); - } - - private: - CarlaMutex& fMutex; - - CARLA_PREVENT_HEAP_ALLOCATION - CARLA_DECLARE_NON_COPY_CLASS(ScopedUnlocker) - }; - private: mutable pthread_mutex_t fMutex; // The mutex mutable volatile bool fTryLockWasCalled; // true if "tryLock()" was called at least once @@ -155,9 +107,14 @@ public: #ifdef CARLA_OS_WIN InitializeCriticalSection(&fSection); #else - fCounter = 0; - fOwnerThread = 0; - pthread_mutex_init(&fMutex, nullptr); + pthread_mutexattr_t atts; + pthread_mutexattr_init(&atts); + pthread_mutexattr_settype(&atts, PTHREAD_MUTEX_RECURSIVE); +# ifndef CARLA_OS_ANDROID + pthread_mutexattr_setprotocol(&atts, PTHREAD_PRIO_INHERIT); +# endif + pthread_mutex_init(&fMutex, &atts); + pthread_mutexattr_destroy(&atts); #endif } @@ -176,79 +133,122 @@ public: /* * Enter section. */ - void enter() noexcept + void enter() const noexcept { #ifdef CARLA_OS_WIN EnterCriticalSection(&fSection); #else - const pthread_t thisThread(pthread_self()); - - if (fOwnerThread == thisThread) - { - ++fCounter; - } - else - { - pthread_mutex_lock(&fMutex); - fOwnerThread = thisThread; - fCounter = 0; - } + pthread_mutex_lock(&fMutex); #endif } /* - * Leave section. + * Try-Enter section. */ - void leave() noexcept + bool tryEnter() const noexcept { #ifdef CARLA_OS_WIN - LeaveCriticalSection(&fSection); + return (TryEnterCriticalSection(&fSection) != FALSE); #else - if (--fCounter < 0) - { - fOwnerThread = 0; - pthread_mutex_unlock(&fMutex); - } + return (pthread_mutex_trylock(&fMutex) == 0); #endif } /* - * Helper class to enter&leave during a function scope. + * Leave section. */ - class Scope + void leave() const noexcept { - public: - Scope(CarlaCriticalSection& cs) noexcept - : fSection(cs) - { - fSection.enter(); - } - - ~Scope() noexcept - { - fSection.leave(); - } - - private: - CarlaCriticalSection& fSection; - - CARLA_PREVENT_HEAP_ALLOCATION - CARLA_DECLARE_NON_COPY_CLASS(Scope) - }; +#ifdef CARLA_OS_WIN + LeaveCriticalSection(&fSection); +#else + pthread_mutex_unlock(&fMutex); +#endif + } private: #ifdef CARLA_OS_WIN - CRITICAL_SECTION fSection; + mutable CRITICAL_SECTION fSection; #else - int fCounter; - pthread_t fOwnerThread; - pthread_mutex_t fMutex; + mutable pthread_mutex_t fMutex; #endif CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(CarlaCriticalSection) }; +// ----------------------------------------------------------------------- +// Helper class to lock&unlock a mutex during a function scope. + +class CarlaMutexLocker +{ +public: + CarlaMutexLocker(const CarlaMutex& mutex) noexcept + : fMutex(mutex) + { + fMutex.lock(); + } + + ~CarlaMutexLocker() noexcept + { + fMutex.unlock(); + } + +private: + const CarlaMutex& fMutex; + + CARLA_PREVENT_HEAP_ALLOCATION + CARLA_DECLARE_NON_COPY_CLASS(CarlaMutexLocker) +}; + +// ----------------------------------------------------------------------- +// Helper class to unlock&lock a mutex during a function scope. + +class CarlaMutexUnlocker +{ +public: + CarlaMutexUnlocker(const CarlaMutex& mutex) noexcept + : fMutex(mutex) + { + fMutex.unlock(); + } + + ~CarlaMutexUnlocker() noexcept + { + fMutex.lock(); + } + +private: + const CarlaMutex& fMutex; + + CARLA_PREVENT_HEAP_ALLOCATION + CARLA_DECLARE_NON_COPY_CLASS(CarlaMutexUnlocker) +}; + +// ----------------------------------------------------------------------- +// Helper class to enter&leave during a function scope. + +class CarlaCriticalSectionScope +{ +public: + CarlaCriticalSectionScope(const CarlaCriticalSection& cs) noexcept + : fSection(cs) + { + fSection.enter(); + } + + ~CarlaCriticalSectionScope() noexcept + { + fSection.leave(); + } + +private: + const CarlaCriticalSection& fSection; + + CARLA_PREVENT_HEAP_ALLOCATION + CARLA_DECLARE_NON_COPY_CLASS(CarlaCriticalSectionScope) +}; + // ----------------------------------------------------------------------- #endif // CARLA_MUTEX_HPP_INCLUDED diff --git a/source/utils/CarlaThread.hpp b/source/utils/CarlaThread.hpp index d867a91e7..18c6c2dd6 100644 --- a/source/utils/CarlaThread.hpp +++ b/source/utils/CarlaThread.hpp @@ -30,7 +30,7 @@ protected: /* * Constructor. */ - CarlaThread(const char* const threadName = nullptr) /*noexcept*/ + CarlaThread(const char* const threadName = nullptr) noexcept : fName(threadName), fShouldExit(false) { @@ -80,7 +80,7 @@ public: { CARLA_SAFE_ASSERT_RETURN(! isThreadRunning(),); - const CarlaMutex::ScopedLocker sl(fLock); + const CarlaMutexLocker sl(fLock); fShouldExit = false; @@ -114,7 +114,7 @@ public: */ bool stopThread(const int timeOutMilliseconds) noexcept { - const CarlaMutex::ScopedLocker sl(fLock); + const CarlaMutexLocker sl(fLock); if (isThreadRunning()) { @@ -172,6 +172,19 @@ private: volatile pthread_t fHandle; // Handle for this thread volatile bool fShouldExit; // true if thread should exit + /* + * Static null thread. + */ + static pthread_t& _null() noexcept + { +#ifdef CARLA_OS_WIN + static pthread_t sThread = { nullptr, 0 }; +#else + static pthread_t sThread = 0; +#endif + return sThread; + } + void _init() noexcept { #ifdef CARLA_OS_WIN diff --git a/source/utils/Lv2AtomQueue.hpp b/source/utils/Lv2AtomQueue.hpp index ce9085f28..fea43e359 100644 --- a/source/utils/Lv2AtomQueue.hpp +++ b/source/utils/Lv2AtomQueue.hpp @@ -198,7 +198,7 @@ public: { CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false); - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker cml(fMutex); return fRingBufferCtrl.writeAtom(atom, static_cast(portIndex)); } @@ -209,7 +209,7 @@ public: CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false); CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker cml(fMutex); return fRingBufferCtrl.writeAtomChunk(atom, data, static_cast(portIndex)); } @@ -236,11 +236,11 @@ public: void copyDataFromQueue(Lv2AtomQueue& queue) { // lock source - const CarlaMutex::ScopedLocker qsl(queue.fMutex); + const CarlaMutexLocker qsl(queue.fMutex); { // copy data from source - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker cml(fMutex); fRingBufferCtrl.fBuffer = queue.fRingBufferCtrl.fBuffer; } @@ -251,11 +251,11 @@ public: void copyAndDumpDataFromQueue(Lv2AtomQueue& queue, char dumpBuf[]) { // lock source - const CarlaMutex::ScopedLocker qsl(queue.fMutex); + const CarlaMutexLocker cml1(queue.fMutex); { // copy data from source - const CarlaMutex::ScopedLocker sl(fMutex); + const CarlaMutexLocker cml2(fMutex); fRingBufferCtrl.copyDump(queue.fRingBufferCtrl.fBuffer, dumpBuf); }