dimanche 23 septembre 2018

ManualResetEvent (from C#) implementation on C++: how to avoid race condition

I'd like to learn more about multithreading programming, and I thought that it would be a good exercise to try to implement some of the C# synchronization primitives in C++.
I've started with ManualResetEvent, and this is what I have so far:

class manual_reset_event
{
public:
    void wait_one()
    {
        if (cv_flag_.load() == false)
        {
            thread_local std::mutex mutex;
            std::unique_lock<std::mutex> lock(mutex);
            cond_var_.wait(lock, [this]() { return cv_flag_.load(); });
        }
    }

    void set()
    {
        cv_flag_.store(true);
    }

    void reset()
    {
        cv_flag_.store(false);
    }

private:
    std::condition_variable cond_var_;
    std::atomic<bool> cv_flag_;
};

However, there is a race condition here: you could call wait_one() on one thread, pass the if (cv_flag) check, and then call set from another thread. This will cause wait_one() to wait, even though cv_flag_ is now true.
I could solve this by using a lock on wait_one, set and reset.
I think I could also solve this by calling cond_var_.notify_all() immediately after cond_var_.wait() on wait_one(), but I don't think this is a great idea (although maybe I'm wrong).
I was wondering if there is something else (maybe even a completely different approach without using conditional_variables) that I can do here to avoid this race condition.

Thank you very much!

Aucun commentaire:

Enregistrer un commentaire