-
Notifications
You must be signed in to change notification settings - Fork 95
3.7 Mutexes and condition variables
We have seen in previous sections that it is possible to write lock-free code by posting coroutines and IO tasks unto specific queues, thus serializing all access to shared code.
Although this solution may be sufficient for most cases, it might be necessary sometimes to modify objects which are shared between a coroutine and an IO task or between a coroutine and some other arbitrary thread outside the control of the dispatcher (e.g. the main program thread), such as those with static storage or global objects. For this specific purpose two classes have been created which will not block a coroutine (we have seen that blocking a coroutine thread can result in performance degradation) called quantum::Mutex
and quantum::ConditionVariable
. These two classes behave exactly as their STL counterparts and they MUST be used when synchronizing access from within a coroutine.
std::vector<int> v; //global object
Mutex m;
ConditionVariable cv;
//synchronize access to the vector from the main thread
m.lock();
//start a couple of coroutines waiting to access the vector
dispatcher.post([](CoroContextPtr<int> ctx,
Mutex& mu,
std::vector<int>& vec,
ConditionVariable& cv)->int
{
mu.lock(ctx);
cv.wait(ctx, mu, [&vec]()->bool{ return !vec.empty(); });
vec.push_back(6);
mu.unlock();
return 0;
}, m, v, cv);
//start the 2nd coroutine
dispatcher.post([](CoroContextPtr<int> ctx,
Mutex& mu,
std::vector<int>& vec,
ConditionVariable& cv)->int
{
mu.lock(ctx);
cv.wait(ctx, mu, [&vec]()->bool{ return !vec.empty(); });
vec.push_back(7);
mu.unlock();
return 0;
}, m, v, cv);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
v.push_back(5);
m.unlock(); //release access to global object
cv.notifyAll();
dispatcher.drain();
//At this point 'v' will contain {5, 6, 7} or {5, 7, 6}.
When it comes to IO tasks, standard std::mutex
and std::condition_variable
can be used as long as the object being synchronized is not accessed by a coroutine.