From f91ee9cdfae31cd5e6841d32b566abd60618d88f Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Tue, 23 Jun 2020 03:56:56 +0200 Subject: [PATCH 1/6] Replace the clearing thread busy wait with semaphore --- src/sfizz/FilePool.cpp | 19 ++++++++++++++----- src/sfizz/FilePool.h | 1 + 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index 95519ac6..b18d5254 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -125,11 +125,16 @@ sfz::FilePool::~FilePool() { quitThread = true; + std::error_code ec; + for (unsigned i = 0; i < threadPool.size(); ++i) { - std::error_code ec; + ec = std::error_code(); workerBarrier.post(ec); } + ec = std::error_code(); + semClearingRequest.post(ec); + for (auto& thread: threadPool) thread.join(); } @@ -360,10 +365,13 @@ void sfz::FilePool::tryToClearPromises() void sfz::FilePool::clearingThread() { - while (!quitThread) { + RTSemaphore& request = semClearingRequest; + do { + request.wait(); + if (quitThread) + return; tryToClearPromises(); - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } + } while (1); } void sfz::FilePool::loadingThread() noexcept @@ -443,7 +451,8 @@ void sfz::FilePool::cleanupPromises() noexcept auto promiseUsedOnce = [](FilePromisePtr& p) { return p.use_count() == 1; }; auto moveToClear = [&](FilePromisePtr& p) { return promisesToClear.push_back(p); }; - swapAndPopAll(temporaryFilePromises, promiseUsedOnce, moveToClear); + if (swapAndPopAll(temporaryFilePromises, promiseUsedOnce, moveToClear) > 0) + semClearingRequest.post(); } void sfz::FilePool::setOversamplingFactor(sfz::Oversampling factor) noexcept diff --git a/src/sfizz/FilePool.h b/src/sfizz/FilePool.h index 25eaf068..1325168c 100644 --- a/src/sfizz/FilePool.h +++ b/src/sfizz/FilePool.h @@ -275,6 +275,7 @@ private: volatile bool emptyQueue { false }; std::atomic threadsLoading { 0 }; RTSemaphore workerBarrier; + RTSemaphore semClearingRequest; // File promises data structures along with their guards. std::vector emptyPromises; From f25dd03db0caff9645d3bdf4d23083ccbce060b2 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Tue, 23 Jun 2020 03:59:20 +0200 Subject: [PATCH 2/6] Replace the queue emptying busy wait with semaphore --- src/sfizz/FilePool.cpp | 16 +++++----------- src/sfizz/FilePool.h | 1 + 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index b18d5254..cc0ed7b8 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -378,19 +378,17 @@ void sfz::FilePool::loadingThread() noexcept { FilePromisePtr promise; while (!quitThread) { + workerBarrier.wait(); if (emptyQueue) { - while(promiseQueue.try_pop(promise)) { + while (promiseQueue.try_pop(promise)) { // We're just dequeuing } emptyQueue = false; + semEmptyQueueFinished.post(); continue; } - std::error_code ec; - workerBarrier.wait(ec); - ASSERT(!ec); - if (!promiseQueue.try_pop(promise)) { continue; } @@ -483,12 +481,8 @@ uint32_t sfz::FilePool::getPreloadSize() const noexcept void sfz::FilePool::emptyFileLoadingQueues() noexcept { emptyQueue = true; - std::error_code ec; - workerBarrier.post(ec); - ASSERT(!ec); - - while (emptyQueue) - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + workerBarrier.post(); + semEmptyQueueFinished.wait(); } void sfz::FilePool::waitForBackgroundLoading() noexcept diff --git a/src/sfizz/FilePool.h b/src/sfizz/FilePool.h index 1325168c..80e7f8a2 100644 --- a/src/sfizz/FilePool.h +++ b/src/sfizz/FilePool.h @@ -273,6 +273,7 @@ private: // Signals volatile bool quitThread { false }; volatile bool emptyQueue { false }; + RTSemaphore semEmptyQueueFinished; std::atomic threadsLoading { 0 }; RTSemaphore workerBarrier; RTSemaphore semClearingRequest; From 26d63a92f0fdcf2c9af6a1e5f6634acbbedbb8c4 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Tue, 23 Jun 2020 04:01:35 +0200 Subject: [PATCH 3/6] Rewrite the loading loop to check quit flag after waiting --- src/sfizz/FilePool.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index cc0ed7b8..65a3b357 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -377,7 +377,7 @@ void sfz::FilePool::clearingThread() void sfz::FilePool::loadingThread() noexcept { FilePromisePtr promise; - while (!quitThread) { + do { workerBarrier.wait(); if (emptyQueue) { @@ -389,6 +389,9 @@ void sfz::FilePool::loadingThread() noexcept continue; } + if (quitThread) + return; + if (!promiseQueue.try_pop(promise)) { continue; } @@ -418,7 +421,7 @@ void sfz::FilePool::loadingThread() noexcept } promise.reset(); - } + } while (1); } void sfz::FilePool::clear() From b0c8495f6c6b9ea5aeb34d4200e8fd3af82609b2 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Tue, 23 Jun 2020 04:03:35 +0200 Subject: [PATCH 4/6] Replace the filled promise queue busy wait with semaphore --- src/sfizz/FilePool.cpp | 10 +++++----- src/sfizz/FilePool.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index 65a3b357..2abf3b45 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -415,10 +415,8 @@ void sfz::FilePool::loadingThread() noexcept threadsLoading--; - while (!filledPromiseQueue.try_push(promise)) { - DBG("[sfizz] Error enqueuing the promise for " << promise->fileId << " in the filledPromiseQueue"); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } + semFilledPromiseQueueAvailable.wait(); + filledPromiseQueue.push(promise); promise.reset(); } while (1); @@ -447,8 +445,10 @@ void sfz::FilePool::cleanupPromises() noexcept // Remove the promises from the filled queue and put them in a linear // storage FilePromisePtr promise; - while (filledPromiseQueue.try_pop(promise)) + while (filledPromiseQueue.try_pop(promise)) { + semFilledPromiseQueueAvailable.post(); temporaryFilePromises.push_back(promise); + } auto promiseUsedOnce = [](FilePromisePtr& p) { return p.use_count() == 1; }; auto moveToClear = [&](FilePromisePtr& p) { return promisesToClear.push_back(p); }; diff --git a/src/sfizz/FilePool.h b/src/sfizz/FilePool.h index 80e7f8a2..ee81c268 100644 --- a/src/sfizz/FilePool.h +++ b/src/sfizz/FilePool.h @@ -268,6 +268,7 @@ private: atomic_queue::AtomicQueue2 promiseQueue; atomic_queue::AtomicQueue2 filledPromiseQueue; + RTSemaphore semFilledPromiseQueueAvailable { config::maxVoices }; uint32_t preloadSize { config::preloadSize }; Oversampling oversamplingFactor { config::defaultOversamplingFactor }; // Signals From 0f10991dd9171ec50e14cac019b21630e118df43 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Tue, 23 Jun 2020 05:00:37 +0200 Subject: [PATCH 5/6] Increase the background thread priority --- src/sfizz/Config.h | 4 ++++ src/sfizz/FilePool.cpp | 45 +++++++++++++++++++++++++++++++++++++++++- src/sfizz/FilePool.h | 5 +++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/sfizz/Config.h b/src/sfizz/Config.h index 918264ca..9268cb89 100644 --- a/src/sfizz/Config.h +++ b/src/sfizz/Config.h @@ -99,6 +99,10 @@ namespace config { static constexpr double amplitudeTriangle = 0.625; static constexpr double amplitudeSaw = 0.515; static constexpr double amplitudeSquare = 0.515; + /** + Background file loading + */ + static constexpr int backgroundLoaderPthreadPriority = 50; // expressed in % } // namespace config } // namespace sfz diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index 2abf3b45..95647340 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -37,8 +37,14 @@ #include "absl/memory/memory.h" #include #include -#include #include +#include +#include +#if defined(_WIN32) +#include +#else +#include +#endif void readBaseFile(SndfileHandle& sndFile, sfz::FileAudioBuffer& output, uint32_t numFrames, bool reverse) { @@ -365,6 +371,8 @@ void sfz::FilePool::tryToClearPromises() void sfz::FilePool::clearingThread() { + raiseCurrentThreadPriority(); + RTSemaphore& request = semClearingRequest; do { request.wait(); @@ -376,6 +384,8 @@ void sfz::FilePool::clearingThread() void sfz::FilePool::loadingThread() noexcept { + raiseCurrentThreadPriority(); + FilePromisePtr promise; do { workerBarrier.wait(); @@ -502,3 +512,36 @@ void sfz::FilePool::waitForBackgroundLoading() noexcept std::this_thread::sleep_for(std::chrono::microseconds(100)); } } + +void sfz::FilePool::raiseCurrentThreadPriority() noexcept +{ +#if defined(_WIN32) + #pragma message("Implement Win32 thread background priority") + HANDLE thread = GetCurrentThread(); + const int priority = THREAD_PRIORITY_ABOVE_NORMAL; /*THREAD_PRIORITY_HIGHEST*/ + if (!SetThreadPriority(thread, priority)) { + std::system_error error(GetLastError(), std::system_category()); + DBG("[sfizz] Cannot set current thread priority: " << error.what()); + } +#else + pthread_t thread = pthread_self(); + int policy; + sched_param param; + + if (pthread_getschedparam(thread, &policy, ¶m) != 0) { + DBG("[sfizz] Cannot get current thread scheduling parameters"); + return; + } + + policy = SCHED_RR; + const int minprio = sched_get_priority_min(policy); + const int maxprio = sched_get_priority_max(policy); + param.sched_priority = minprio + + config::backgroundLoaderPthreadPriority * (maxprio - minprio) / 100; + + if (pthread_setschedparam(thread, policy, ¶m) != 0) { + DBG("[sfizz] Cannot set current thread scheduling parameters"); + return; + } +#endif +} diff --git a/src/sfizz/FilePool.h b/src/sfizz/FilePool.h index ee81c268..2547591f 100644 --- a/src/sfizz/FilePool.h +++ b/src/sfizz/FilePool.h @@ -259,6 +259,11 @@ public: * in the queue. */ void waitForBackgroundLoading() noexcept; + /** + * @brief Assign the current thread a priority which is appropriate + * for background sample file processing. + */ + static void raiseCurrentThreadPriority() noexcept; private: Logger& logger; fs::path rootDirectory; From 957d1b18649fb8b46db87eed1a41bf49c821ac7e Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Tue, 23 Jun 2020 05:37:27 +0200 Subject: [PATCH 6/6] Remove irrelevant warning pragma --- src/sfizz/FilePool.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index 95647340..9bec98ef 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -516,7 +516,6 @@ void sfz::FilePool::waitForBackgroundLoading() noexcept void sfz::FilePool::raiseCurrentThreadPriority() noexcept { #if defined(_WIN32) - #pragma message("Implement Win32 thread background priority") HANDLE thread = GetCurrentThread(); const int priority = THREAD_PRIORITY_ABOVE_NORMAL; /*THREAD_PRIORITY_HIGHEST*/ if (!SetThreadPriority(thread, priority)) {