diff --git a/include/sgnl/AtomicCondition.h b/include/sgnl/AtomicCondition.h index 7e30b28..80ed484 100644 --- a/include/sgnl/AtomicCondition.h +++ b/include/sgnl/AtomicCondition.h @@ -18,7 +18,7 @@ class AtomicCondition public: explicit AtomicCondition(ValueType val) : value_(val) - , condvar_mutex_() + , mutex_() , condvar_() { } @@ -30,14 +30,23 @@ public: void set(ValueType val) noexcept { - this->value_.store(val); + { + // This ensures that wait_for is either + // 1. not running, or + // 2. in a waiting state + // to avoid a data race between value_.load and cond_var.wait_for. + std::unique_lock lock(this->mutex_); + this->value_.store(val); + } + + this->condvar_.notify_all(); } template void wait_for(const std::chrono::duration& time, ValueType val) const { - std::unique_lock lock(this->condvar_mutex_); + std::unique_lock lock(this->mutex_); while( this->value_.load() != val ) if( this->condvar_.wait_for(lock, time) == std::cv_status::timeout ) @@ -48,26 +57,16 @@ public: void wait_for(const std::chrono::duration& time, Predicate pred) const { - std::unique_lock lock(this->condvar_mutex_); + std::unique_lock lock(this->mutex_); while( !pred() ) if( this->condvar_.wait_for(lock, time) == std::cv_status::timeout ) return; } - void notify_one() noexcept - { - this->condvar_.notify_one(); - } - - void notify_all() noexcept - { - this->condvar_.notify_all(); - } - private: std::atomic value_; - mutable std::mutex condvar_mutex_; + mutable std::mutex mutex_; mutable std::condition_variable condvar_; }; diff --git a/include/sgnl/SignalHandler.h b/include/sgnl/SignalHandler.h index 04410d1..ee7ca92 100644 --- a/include/sgnl/SignalHandler.h +++ b/include/sgnl/SignalHandler.h @@ -58,7 +58,6 @@ public: it != this->signal_map_.end() ) { this->condition_.set(it->second); - this->condition_.notify_all(); return it->first; } } diff --git a/test/test.cpp b/test/test.cpp index 751993c..9ccd3f8 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -58,7 +58,6 @@ TEST_CASE("wait-for-value") std::this_thread::yield(); condition.set(42); - condition.notify_one(); future.get(); REQUIRE( condition.get() == 42 ); @@ -79,7 +78,6 @@ TEST_CASE("wait-for-predicate") std::this_thread::yield(); condition.set(42); - condition.notify_one(); future.get(); REQUIRE( condition.get() == 42 );