From f62a81797a731595353a2d48499dec9457e37946 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 17 Jul 2020 23:37:33 +0200 Subject: [PATCH] AtomicCondition: add wait*_value helpers --- include/sgnl/AtomicCondition.h | 36 +++++++++++++++++++++ test/test.cpp | 59 ++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/include/sgnl/AtomicCondition.h b/include/sgnl/AtomicCondition.h index 07fd8e3..2d2a7f1 100644 --- a/include/sgnl/AtomicCondition.h +++ b/include/sgnl/AtomicCondition.h @@ -65,6 +65,18 @@ public: return this->condvar_.wait(lock, std::forward(args)...); } + template + auto wait_value(ValueType value, Args&&... args) const + { + std::unique_lock lock(this->mutex_); + return this->condvar_.wait( + lock, + std::forward(args)..., + [this, &value](){ + return this->value_.load() == value; + }); + } + template auto wait_for(Args&&... args) const { @@ -72,6 +84,18 @@ public: return this->condvar_.wait_for(lock, std::forward(args)...); } + template + auto wait_for_value(ValueType value, Args&&... args) const + { + std::unique_lock lock(this->mutex_); + return this->condvar_.wait_for( + lock, + std::forward(args)..., + [this, &value](){ + return this->value_.load() == value; + }); + } + template auto wait_until(Args&&... args) const { @@ -79,6 +103,18 @@ public: return this->condvar_.wait_until(lock, std::forward(args)...); } + template + auto wait_until_value(ValueType value, Args&&... args) const + { + std::unique_lock lock(this->mutex_); + return this->condvar_.wait_until( + lock, + std::forward(args)..., + [this, &value](){ + return this->value_.load() == value; + }); + } + private: std::atomic value_; mutable std::mutex mutex_; diff --git a/test/test.cpp b/test/test.cpp index f0d3d10..d7ab3ed 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -85,6 +85,23 @@ TEST_CASE("wait-pred") REQUIRE( future.get() == true ); } +TEST_CASE("wait-value") +{ + sgnl::AtomicCondition condition(0); + std::future future = + std::async( + std::launch::async, + [&condition](){ condition.wait_value(23); return condition.get(); }); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::yield(); + + condition.notify_all(); + condition.set_and_notify_one(23); + + REQUIRE( future.get() == 23 ); +} + TEST_CASE("wait-for-predicate") { sgnl::AtomicCondition condition(23); @@ -105,6 +122,24 @@ TEST_CASE("wait-for-predicate") REQUIRE( condition.get() == 42 ); } +TEST_CASE("wait-for-value") +{ + sgnl::AtomicCondition condition(23); + std::future future = + std::async( + std::launch::async, + [&condition](){ + condition.wait_for_value(42, std::chrono::hours(1000)); }); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::yield(); + + condition.set_and_notify_all(42); + future.wait(); + + REQUIRE( condition.get() == 42 ); +} + TEST_CASE("wait-for-predicate-simple") { sgnl::AtomicCondition condition(23); @@ -146,6 +181,30 @@ TEST_CASE("wait-until-predicate") REQUIRE( condition.get() == 42 ); } +TEST_CASE("wait-until-value") +{ + sgnl::AtomicCondition condition(23); + std::future future = + std::async( + std::launch::async, + [&condition](){ + condition.wait_until_value( + 42, + std::chrono::system_clock::now() + std::chrono::hours(1)); + return condition.get(); + }); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::yield(); + + condition.notify_all(); + condition.set(42); + condition.notify_all(); + + REQUIRE( future.get() == 42 ); + REQUIRE( condition.get() == 42 ); +} + TEST_CASE("sigwait") { sgnl::SignalHandler signal_handler({SIGUSR1});