From e1683afb3145de9e49efd5f78dde8ebcbff60c4a Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Wed, 12 Apr 2023 14:49:48 +0200 Subject: [PATCH] Internals: V3ThreadPool: add function waiting for list of futures (#4112) --- src/V3ThreadPool.cpp | 12 +++------- src/V3ThreadPool.h | 52 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/src/V3ThreadPool.cpp b/src/V3ThreadPool.cpp index bcea59291..47750a093 100644 --- a/src/V3ThreadPool.cpp +++ b/src/V3ThreadPool.cpp @@ -182,18 +182,12 @@ void V3ThreadPool::selfTest() { } futures.push_back(s().enqueue(std::bind(thirdJob, 100))); futures.push_back(s().enqueue(std::bind(thirdJob, 100))); - while (!futures.empty()) { - s().waitForFuture(futures.front()); - futures.pop_front(); - } + V3ThreadPool::waitForFutures(futures); s().waitIfStopRequested(); s().requestExclusiveAccess(std::bind(firstJob, 100)); auto forthJob = [&]() -> int { return 1234; }; std::list> futuresInt; futuresInt.push_back(s().enqueue(forthJob)); - while (!futuresInt.empty()) { - int result = s().waitForFuture(futuresInt.front()); - UASSERT(result == 1234, "unexpected future result = " << commonValue); - futuresInt.pop_front(); - } + auto result = V3ThreadPool::waitForFutures(futuresInt); + UASSERT(result.back() == 1234, "unexpected future result = " << result.back()); } diff --git a/src/V3ThreadPool.h b/src/V3ThreadPool.h index 76eaecfbb..c7f92195a 100644 --- a/src/V3ThreadPool.h +++ b/src/V3ThreadPool.h @@ -27,6 +27,19 @@ #include #include +namespace future_type { +template +struct return_type { + typedef std::list type; +}; + +template <> +struct return_type { + typedef void type; +}; + +} // namespace future_type + //============================================================================ class V3ThreadPool final { @@ -88,12 +101,47 @@ public: // Returns true if request was send and we waited, otherwise false bool waitIfStopRequested() VL_MT_SAFE; + // Waits for future. + // This function can be interupted by exclusive access request. + // When other thread requested exclusive access to processing, + // current thread is stopped and waits until it is resumed. + // Returns future result template - T waitForFuture(std::future& future) VL_MT_SAFE_EXCLUDES(m_mutex); + static T waitForFuture(std::future& future) VL_MT_SAFE_EXCLUDES(m_mutex); + + // Waits for list of futures + // This function can be interupted by exclusive access request. + // When other thread requested exclusive access to processing, + // current thread is stopped and waits until it is resumed. + // This function uses function overload instead of template + // specialization as C++11 requires them to be inside namespace scope + // Returns list of future result or void + template + static typename future_type::return_type::type + waitForFutures(std::list>& futures) { + return waitForFuturesImp(futures); + } static void selfTest(); private: + template + static typename future_type::return_type::type + waitForFuturesImp(std::list>& futures) { + typename future_type::return_type::type results; + while (!futures.empty()) { + results.push_back(V3ThreadPool::waitForFuture(futures.front())); + futures.pop_front(); + } + return results; + } + + static void waitForFuturesImp(std::list>& futures) { + while (!futures.empty()) { + V3ThreadPool::waitForFuture(futures.front()); + futures.pop_front(); + } + } bool willExecuteSynchronously() const VL_MT_SAFE { return m_workers.empty() || m_exclusiveAccess; } @@ -128,7 +176,7 @@ private: template T V3ThreadPool::waitForFuture(std::future& future) VL_MT_SAFE_EXCLUDES(m_mutex) { while (true) { - waitIfStopRequested(); + V3ThreadPool::s().waitIfStopRequested(); { std::future_status status = future.wait_for(std::chrono::milliseconds(V3ThreadPool::FUTUREWAITFOR_MS));