Reputation: 309
Suppose I have a class with the following interface:
class IEvent
{
void SetEvent() = 0;
void WaitForEvent() = 0;
}
WaitForEvent()
is a blocking function which waits until another thread calls SetEvent()
function.
I'm writing unit tests for this class and want following scenario:
First thread calls WaitForEvent()
. After that second thread calls SetEvent()
.
How to synchronize this threads that SetEvent()
call will always follow WaitForEvent()
call?
I don't want to use any sleeps because I want unit tests to run as fast as possible.
Upvotes: 0
Views: 714
Reputation: 69854
This was the best I could manage
#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>
class IEvent
{
public:
virtual void SetEvent() = 0;
virtual void WaitForEvent() = 0;
};
class EventClass : public IEvent
{
public:
void SetEvent() override {
std::unique_lock<std::mutex> lock { _mutex };
std::cout << "setting event\n";
_event = true;
lock.unlock();
_cv.notify_all();
}
void WaitForEvent() override {
std::unique_lock<std::mutex> lock { _mutex };
std::cout << "waiting for event\n";
_cv.wait(lock, [this]{ return _event; });
std::cout << "waiting complete\n";
};
private:
std::mutex _mutex;
std::condition_variable _cv;
bool _event = false;
};
int main()
{
EventClass object;
std::mutex cv_mutex;
std::condition_variable may_set_cv;
bool may_set_event = false;
auto setting_thread = std::thread([&]{
std::unique_lock<std::mutex> lock { cv_mutex };
may_set_cv.wait(lock,
[&] {
return may_set_event;
});
object.SetEvent();
});
std::unique_lock<std::mutex> lock { cv_mutex };
may_set_event = true;
lock.unlock();
may_set_cv.notify_one();
// tiny race condition here
object.WaitForEvent();
setting_thread.join();
}
Upvotes: 1