Fix ringing with non-truthy values in alarm_t

The Windows mDNS registration code does this in the failure path and ends up deadlocking.
This commit is contained in:
Cameron Gutman 2023-04-28 00:08:44 -05:00
parent d05dc731be
commit 4668ff59e5

View File

@ -141,14 +141,12 @@ namespace safe {
public: public:
using status_t = util::optional_t<T>; using status_t = util::optional_t<T>;
alarm_raw_t():
_status { util::false_v<status_t> } {}
void void
ring(const status_t &status) { ring(const status_t &status) {
std::lock_guard lg(_lock); std::lock_guard lg(_lock);
_status = status; _status = status;
_rang = true;
_cv.notify_one(); _cv.notify_one();
} }
@ -157,6 +155,7 @@ namespace safe {
std::lock_guard lg(_lock); std::lock_guard lg(_lock);
_status = std::move(status); _status = std::move(status);
_rang = true;
_cv.notify_one(); _cv.notify_one();
} }
@ -165,7 +164,7 @@ namespace safe {
wait_for(const std::chrono::duration<Rep, Period> &rel_time) { wait_for(const std::chrono::duration<Rep, Period> &rel_time) {
std::unique_lock ul(_lock); 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> 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) { wait_for(const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
std::unique_lock ul(_lock); 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> template <class Rep, class Period>
@ -181,7 +180,7 @@ namespace safe {
wait_until(const std::chrono::duration<Rep, Period> &rel_time) { wait_until(const std::chrono::duration<Rep, Period> &rel_time) {
std::unique_lock ul(_lock); 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> 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) { wait_until(const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
std::unique_lock ul(_lock); 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 auto
wait() { wait() {
std::unique_lock ul(_lock); std::unique_lock ul(_lock);
_cv.wait(ul, [this]() { return (bool) status(); }); _cv.wait(ul, [this]() { return _rang; });
} }
template <class Pred> template <class Pred>
auto auto
wait(Pred &&pred) { wait(Pred &&pred) {
std::unique_lock ul(_lock); 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 & const status_t &
@ -218,13 +217,15 @@ namespace safe {
void void
reset() { reset() {
_status = status_t {}; _status = status_t {};
_rang = false;
} }
private: private:
std::mutex _lock; std::mutex _lock;
std::condition_variable _cv; std::condition_variable _cv;
status_t _status; status_t _status { util::false_v<status_t> };
bool _rang { false };
}; };
template <class T> template <class T>