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 <liamwhite@users.noreply.github.com>
This commit is contained in:
Morph 2023-01-25 16:03:32 -05:00
parent b82a098968
commit 9b0563fa87
1 changed files with 36 additions and 0 deletions

View File

@ -11,6 +11,8 @@
#ifdef __cpp_lib_jthread #ifdef __cpp_lib_jthread
#include <chrono>
#include <condition_variable>
#include <stop_token> #include <stop_token>
#include <thread> #include <thread>
@ -21,11 +23,23 @@ void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) {
cv.wait(lock, token, std::move(pred)); cv.wait(lock, token, std::move(pred));
} }
template <typename Rep, typename Period>
bool StoppableTimedWait(std::stop_token token, const std::chrono::duration<Rep, Period>& 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 } // namespace Common
#else #else
#include <atomic> #include <atomic>
#include <chrono>
#include <condition_variable>
#include <functional> #include <functional>
#include <list> #include <list>
#include <memory> #include <memory>
@ -318,6 +332,28 @@ void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred pred) {
cv.wait(lock, [&] { return pred() || token.stop_requested(); }); cv.wait(lock, [&] { return pred() || token.stop_requested(); });
} }
template <typename Rep, typename Period>
bool StoppableTimedWait(std::stop_token token, const std::chrono::duration<Rep, Period>& 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 } // namespace Common
#endif #endif