Reputation: 35485
I want to implement a mechanism that allows me to block program flow until an async operation has completed. (Mostly to be used in unit tests where there is no message loop.)
The code I have creates a thread and waits for a condition notification inside the thread:
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <thread>
struct Blocker {
Blocker() :
wait_thread([this]() {
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
cond.wait(lck);
})
{
}
void wait() { wait_thread.join(); }
void notify() { cond.notify_one(); }
std::condition_variable cond;
std::thread wait_thread;
};
template<typename Callback>
void async_operation(const Callback & cb) { cb(); }
int main() {
Blocker b;
async_operation([&](){ b.notify(); });
b.wait();
}
The problem is that it often deadlocks because the call to notify
occurs before the thread even started. How should I fix this?
Upvotes: 1
Views: 1792
Reputation: 16888
#include <mutex>
#include <condition_variable>
struct blocker
{
blocker () : done (false) {}
void
notify ()
{
std::unique_lock<std::mutex> lock (m);
done = true;
c.notify_all ();
}
void
wait ()
{
std::unique_lock<std::mutex> lock (m);
while (!done)
c.wait (lock);
}
bool done;
std::mutex m;
std::condition_variable c;
};
Upvotes: 3