Ver código fonte

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>
Morph 3 anos atrás
pai
commit
9b0563fa87
1 arquivos alterados com 36 adições e 0 exclusões
  1. 36 0
      src/common/polyfill_thread.h

+ 36 - 0
src/common/polyfill_thread.h

@@ -11,6 +11,8 @@
 
 #ifdef __cpp_lib_jthread
 
+#include <chrono>
+#include <condition_variable>
 #include <stop_token>
 #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));
 }
 
+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
 
 #else
 
 #include <atomic>
+#include <chrono>
+#include <condition_variable>
 #include <functional>
 #include <list>
 #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(); });
 }
 
+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
 
 #endif