From 4668ff59e5cc6bdd52db800801a726f12357196b Mon Sep 17 00:00:00 2001 From: Cameron Gutman <aicommander@gmail.com> Date: Fri, 28 Apr 2023 00:08:44 -0500 Subject: [PATCH] Fix ringing with non-truthy values in alarm_t The Windows mDNS registration code does this in the failure path and ends up deadlocking. --- src/thread_safe.h | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/thread_safe.h b/src/thread_safe.h index 6db1e9ec..f69f0a5b 100644 --- a/src/thread_safe.h +++ b/src/thread_safe.h @@ -141,14 +141,12 @@ namespace safe { public: using status_t = util::optional_t<T>; - alarm_raw_t(): - _status { util::false_v<status_t> } {} - void ring(const status_t &status) { std::lock_guard lg(_lock); _status = status; + _rang = true; _cv.notify_one(); } @@ -157,6 +155,7 @@ namespace safe { std::lock_guard lg(_lock); _status = std::move(status); + _rang = true; _cv.notify_one(); } @@ -165,7 +164,7 @@ namespace safe { wait_for(const std::chrono::duration<Rep, Period> &rel_time) { std::unique_lock ul(_lock); - return _cv.wait_for(ul, rel_time, [this]() { return (bool) status(); }); + return _cv.wait_for(ul, rel_time, [this]() { return _rang; }); } template <class Rep, class Period, class Pred> @@ -173,7 +172,7 @@ namespace safe { wait_for(const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) { std::unique_lock ul(_lock); - return _cv.wait_for(ul, rel_time, [this, &pred]() { return (bool) status() || pred(); }); + return _cv.wait_for(ul, rel_time, [this, &pred]() { return _rang || pred(); }); } template <class Rep, class Period> @@ -181,7 +180,7 @@ namespace safe { wait_until(const std::chrono::duration<Rep, Period> &rel_time) { std::unique_lock ul(_lock); - return _cv.wait_until(ul, rel_time, [this]() { return (bool) status(); }); + return _cv.wait_until(ul, rel_time, [this]() { return _rang; }); } template <class Rep, class Period, class Pred> @@ -189,20 +188,20 @@ namespace safe { wait_until(const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) { std::unique_lock ul(_lock); - return _cv.wait_until(ul, rel_time, [this, &pred]() { return (bool) status() || pred(); }); + return _cv.wait_until(ul, rel_time, [this, &pred]() { return _rang || pred(); }); } auto wait() { std::unique_lock ul(_lock); - _cv.wait(ul, [this]() { return (bool) status(); }); + _cv.wait(ul, [this]() { return _rang; }); } template <class Pred> auto wait(Pred &&pred) { std::unique_lock ul(_lock); - _cv.wait(ul, [this, &pred]() { return (bool) status() || pred(); }); + _cv.wait(ul, [this, &pred]() { return _rang || pred(); }); } const status_t & @@ -218,13 +217,15 @@ namespace safe { void reset() { _status = status_t {}; + _rang = false; } private: std::mutex _lock; std::condition_variable _cv; - status_t _status; + status_t _status { util::false_v<status_t> }; + bool _rang { false }; }; template <class T>