On 2/7/2019 3:43 AM, Sam wrote:
>
mvor...@gmail.com writes:
>
>> I would like to implement an event class in C++: an object that can be
>> signaled to wake up another thread(s), and upon signal it can stay
>> signaled or reset itself to non signaled if it wakes up 1 thread.
>> below is my attempt at implementing such a class using a condition
>> variable. is this a viable approach?
>
> Generally viable, but there are some obvious bugs. Several operations
> block on change to m_signaled, using a condition variable. Several
> operations that update m_signaled fail to notify the condition variable.
>
> Since the condition variable is used to wait for a change to m_signaled,
> all code paths that modify m_signaled should notify the condition variable.
Why would one need to notify the condition variable on a reset?
>> #pragma once
>>
>> #include <mutex>
>> #include <atomic>
>> #include <condition_variable>
>>
>> class event
>> {
>> public:
>> void signal() noexcept
>> {
>> {
>> std::unique_lock<std::mutex> lock(m_mutex);
>> m_signaled = true;
>> }
>> m_cv.notify_all();
>> }
>>
>> void wait(bool reset = false) noexcept
>> {
>> std::unique_lock<std::mutex> lock(m_mutex);
>> m_cv.wait(lock, [&](){ return m_signaled; });
>> if(reset) m_signaled = false;
>> }
The wait wrt the reset parameter is fairly dangerous here. It allows one
to mix and match an auto-reset event with a manual-reset event. This is
not Kosher, and can lead to deadlock conditions. Creating two distinct
classes, auto-reset and manual-reset would help solve this issue.
>> void reset() noexcept
>> {
>> std::unique_lock<std::mutex> lock(m_mutex);
>> m_signaled = false;
>> }
No need to signal anything here, even though we mutated the predicate of
the condition variable.