From d5d2d5befc818e2b5d8370d4024e5ad5b8b3d6c4 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 1 Jan 2022 16:22:17 +0000 Subject: [PATCH] Update fundamental and Rack --- plugins/Fundamental | 2 +- src/Rack | 2 +- src/override/Engine.cpp | 107 +++++++++++----------------------------- src/override/Window.cpp | 7 +++ 4 files changed, 38 insertions(+), 80 deletions(-) diff --git a/plugins/Fundamental b/plugins/Fundamental index e7c2fe6..6012b6e 160000 --- a/plugins/Fundamental +++ b/plugins/Fundamental @@ -1 +1 @@ -Subproject commit e7c2fe6d54531fd2fd25014dc722a18546393207 +Subproject commit 6012b6e49a88d528d7c85a651e7261a1aa2cc575 diff --git a/src/Rack b/src/Rack index 9ad5332..2dc8050 160000 --- a/src/Rack +++ b/src/Rack @@ -1 +1 @@ -Subproject commit 9ad53329fff74989daf3365600f9fccc0b6f5266 +Subproject commit 2dc80509d29880e8b8ca67ba5d1af4835a6b6cad diff --git a/src/override/Engine.cpp b/src/override/Engine.cpp index 411b601..7f98fda 100644 --- a/src/override/Engine.cpp +++ b/src/override/Engine.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -41,6 +40,7 @@ #include #include #include +#include #include #ifdef NDEBUG @@ -53,55 +53,6 @@ namespace rack { namespace engine { -/** Allows multiple "reader" threads to obtain a lock simultaneously, but only one "writer" thread. -This implementation is currently just a wrapper for pthreads, which works on Linux/Mac/. -This is available in C++17 as std::shared_mutex, but unfortunately we're using C++11. -*/ -struct ReadWriteMutex { - pthread_rwlock_t rwlock; - - ReadWriteMutex() { - if (pthread_rwlock_init(&rwlock, nullptr)) - throw Exception("pthread_rwlock_init failed"); - } - ~ReadWriteMutex() { - pthread_rwlock_destroy(&rwlock); - } - void lockReader() { - DISTRHO_SAFE_ASSERT_RETURN(pthread_rwlock_rdlock(&rwlock) == 0,); - } - void unlockReader() { - DISTRHO_SAFE_ASSERT_RETURN(pthread_rwlock_unlock(&rwlock) == 0,); - } - void lockWriter() { - DISTRHO_SAFE_ASSERT_RETURN(pthread_rwlock_wrlock(&rwlock) == 0,); - } - void unlockWriter() { - DISTRHO_SAFE_ASSERT_RETURN(pthread_rwlock_unlock(&rwlock) == 0,); - } -}; - -struct ReadLock { - ReadWriteMutex& m; - ReadLock(ReadWriteMutex& m) : m(m) { - m.lockReader(); - } - ~ReadLock() { - m.unlockReader(); - } -}; - -struct WriteLock { - ReadWriteMutex& m; - WriteLock(ReadWriteMutex& m) : m(m) { - m.lockWriter(); - } - ~WriteLock() { - m.unlockWriter(); - } -}; - - struct Engine::Internal { std::vector modules; std::vector cables; @@ -139,7 +90,7 @@ struct Engine::Internal { Writers lock when mutating the engine's state or stepping the block. Readers lock when using the engine's state. */ - ReadWriteMutex mutex; + SharedMutex mutex; }; @@ -329,7 +280,7 @@ Engine::~Engine() { void Engine::clear() { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); clear_NoLock(); } @@ -358,7 +309,7 @@ void Engine::stepBlock(int frames) { // Start timer before locking double startTime = system::getTime(); - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); // Configure thread random::init(); @@ -420,7 +371,7 @@ float Engine::getSampleRate() { void Engine::setSampleRate(float sampleRate) { if (sampleRate == internal->sampleRate) return; - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); internal->sampleRate = sampleRate; internal->sampleTime = 1.f / sampleRate; @@ -498,7 +449,7 @@ size_t Engine::getNumModules() { size_t Engine::getModuleIds(int64_t* moduleIds, size_t len) { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); size_t i = 0; for (Module* m : internal->modules) { if (i >= len) @@ -511,7 +462,7 @@ size_t Engine::getModuleIds(int64_t* moduleIds, size_t len) { std::vector Engine::getModuleIds() { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); std::vector moduleIds; moduleIds.reserve(internal->modules.size()); for (Module* m : internal->modules) { @@ -522,7 +473,7 @@ std::vector Engine::getModuleIds() { void Engine::addModule(Module* module) { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); DISTRHO_SAFE_ASSERT_RETURN(module,); // Check that the module is not already added auto it = std::find(internal->modules.begin(), internal->modules.end(), module); @@ -552,7 +503,7 @@ void Engine::addModule(Module* module) { void Engine::removeModule(Module* module) { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); removeModule_NoLock(module); } @@ -606,7 +557,7 @@ void Engine::removeModule_NoLock(Module* module) { bool Engine::hasModule(Module* module) { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); // TODO Performance could be improved by searching modulesCache, but more testing would be needed to make sure it's always valid. auto it = std::find(internal->modules.begin(), internal->modules.end(), module); return it != internal->modules.end(); @@ -614,7 +565,7 @@ bool Engine::hasModule(Module* module) { Module* Engine::getModule(int64_t moduleId) { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); return getModule_NoLock(moduleId); } @@ -628,7 +579,7 @@ Module* Engine::getModule_NoLock(int64_t moduleId) { void Engine::resetModule(Module* module) { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); DISTRHO_SAFE_ASSERT_RETURN(module,); Module::ResetEvent eReset; @@ -637,7 +588,7 @@ void Engine::resetModule(Module* module) { void Engine::randomizeModule(Module* module) { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); DISTRHO_SAFE_ASSERT_RETURN(module,); Module::RandomizeEvent eRandomize; @@ -650,7 +601,7 @@ void Engine::bypassModule(Module* module, bool bypassed) { if (module->isBypassed() == bypassed) return; - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); // Clear outputs and set to 1 channel for (Output& output : module->outputs) { @@ -673,26 +624,26 @@ void Engine::bypassModule(Module* module, bool bypassed) { json_t* Engine::moduleToJson(Module* module) { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); return module->toJson(); } void Engine::moduleFromJson(Module* module, json_t* rootJ) { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); module->fromJson(rootJ); } void Engine::prepareSaveModule(Module* module) { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); Module::SaveEvent e; module->onSave(e); } void Engine::prepareSave() { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); for (Module* module : internal->modules) { Module::SaveEvent e; module->onSave(e); @@ -706,7 +657,7 @@ size_t Engine::getNumCables() { size_t Engine::getCableIds(int64_t* cableIds, size_t len) { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); size_t i = 0; for (Cable* c : internal->cables) { if (i >= len) @@ -719,7 +670,7 @@ size_t Engine::getCableIds(int64_t* cableIds, size_t len) { std::vector Engine::getCableIds() { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); std::vector cableIds; cableIds.reserve(internal->cables.size()); for (Cable* c : internal->cables) { @@ -730,7 +681,7 @@ std::vector Engine::getCableIds() { void Engine::addCable(Cable* cable) { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); DISTRHO_SAFE_ASSERT_RETURN(cable,); // Check cable properties DISTRHO_SAFE_ASSERT_RETURN(cable->inputModule,); @@ -775,7 +726,7 @@ void Engine::addCable(Cable* cable) { void Engine::removeCable(Cable* cable) { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); removeCable_NoLock(cable); } @@ -816,7 +767,7 @@ void Engine::removeCable_NoLock(Cable* cable) { bool Engine::hasCable(Cable* cable) { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); // TODO Performance could be improved by searching cablesCache, but more testing would be needed to make sure it's always valid. auto it = std::find(internal->cables.begin(), internal->cables.end(), cable); return it != internal->cables.end(); @@ -824,7 +775,7 @@ bool Engine::hasCable(Cable* cable) { Cable* Engine::getCable(int64_t cableId) { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); auto it = internal->cablesCache.find(cableId); if (it == internal->cablesCache.end()) return NULL; @@ -867,7 +818,7 @@ float Engine::getParamSmoothValue(Module* module, int paramId) { void Engine::addParamHandle(ParamHandle* paramHandle) { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); // New ParamHandles must be blank. // This means we don't have to refresh the cache. DISTRHO_SAFE_ASSERT_RETURN(paramHandle->moduleId < 0,); @@ -883,7 +834,7 @@ void Engine::addParamHandle(ParamHandle* paramHandle) { void Engine::removeParamHandle(ParamHandle* paramHandle) { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); removeParamHandle_NoLock(paramHandle); } @@ -901,7 +852,7 @@ void Engine::removeParamHandle_NoLock(ParamHandle* paramHandle) { ParamHandle* Engine::getParamHandle(int64_t moduleId, int paramId) { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); return getParamHandle_NoLock(moduleId, paramId); } @@ -920,7 +871,7 @@ ParamHandle* Engine::getParamHandle(Module* module, int paramId) { void Engine::updateParamHandle(ParamHandle* paramHandle, int64_t moduleId, int paramId, bool overwrite) { - WriteLock lock(internal->mutex); + std::lock_guard lock(internal->mutex); updateParamHandle_NoLock(paramHandle, moduleId, paramId, overwrite); } @@ -963,7 +914,7 @@ void Engine::updateParamHandle_NoLock(ParamHandle* paramHandle, int64_t moduleId json_t* Engine::toJson() { - ReadLock lock(internal->mutex); + SharedLock lock(internal->mutex); json_t* rootJ = json_object(); // modules diff --git a/src/override/Window.cpp b/src/override/Window.cpp index be4eccf..6baa749 100644 --- a/src/override/Window.cpp +++ b/src/override/Window.cpp @@ -143,6 +143,7 @@ struct Window::Internal { std::map> imageCache; bool fbDirtyOnSubpixelChange = true; + int fbCount = 0; Internal() : hiddenApp(false), @@ -343,6 +344,7 @@ void Window::step() { double lastFrameTime = internal->frameTime; internal->frameTime = frameTime; internal->lastFrameDuration = frameTime - lastFrameTime; + internal->fbCount = 0; // DEBUG("%.2lf Hz", 1.0 / internal->lastFrameDuration); // Make event handlers and step() have a clean NanoVG context @@ -515,6 +517,11 @@ bool& Window::fbDirtyOnSubpixelChange() { } +int& Window::fbCount() { + return internal->fbCount; +} + + } // namespace window } // namespace rack