From 9b0563fa878c6afa73e00a967bc24259ec72ef35 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Wed, 25 Jan 2023 16:03:32 -0500 Subject: [PATCH] polyfill_thread: Implement StoppableTimedWait StoppableTimedWait allows for a timed wait to be stopped immediately after a stop is requested. This is useful in cases where long duration thread sleeps are needed and allows for immediate joining of waiting threads after a stop is requested. Co-Authored-By: liamwhite --- src/common/polyfill_thread.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h index 5a8d1ce08..b2c929d2f 100644 --- a/src/common/polyfill_thread.h +++ b/src/common/polyfill_thread.h @@ -11,6 +11,8 @@ #ifdef __cpp_lib_jthread +#include +#include #include #include @@ -21,11 +23,23 @@ void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) { cv.wait(lock, token, std::move(pred)); } +template +bool StoppableTimedWait(std::stop_token token, const std::chrono::duration& rel_time) { + std::condition_variable_any cv; + std::mutex m; + + // Perform the timed wait. + std::unique_lock lk{m}; + return !cv.wait_for(lk, token, rel_time, [&] { return token.stop_requested(); }); +} + } // namespace Common #else #include +#include +#include #include #include #include @@ -318,6 +332,28 @@ void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred pred) { cv.wait(lock, [&] { return pred() || token.stop_requested(); }); } +template +bool StoppableTimedWait(std::stop_token token, const std::chrono::duration& rel_time) { + if (token.stop_requested()) { + return false; + } + + bool stop_requested = false; + std::condition_variable cv; + std::mutex m; + + std::stop_callback cb(token, [&] { + // Wake up the waiting thread. + std::unique_lock lk{m}; + stop_requested = true; + cv.notify_one(); + }); + + // Perform the timed wait. + std::unique_lock lk{m}; + return !cv.wait_for(lk, rel_time, [&] { return stop_requested; }); +} + } // namespace Common #endif