Sunday 8 September 2013

Are there alternative ways to catch potentially missed signals with condition variables?

Are there alternative ways to catch potentially missed signals with
condition variables?

Consider the following simplified example:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mutex;
std::condition_variable cv;
bool cv_flag = false; // I'm talking about this flag here
void startThread1()
{
std::cout << "thread 1 prints first\n";
{
// Set the flag (lock to be safe)
std::unique_lock<std::mutex> lock(mutex);
cv_flag = true;
}
cv.notify_one();
}
void startThread2()
{
std::unique_lock<std::mutex> lock(mutex);
if (!cv_flag)
{
cv.wait(lock);
}
std::cout << "thread 2 prints second\n";
}
int main()
{
std::thread thread1(startThread1);
std::thread thread2(startThread2);
thread1.join();
thread2.join();
}
Here, cv_flag is used to make sure that thread 2 does not lock and wait()
if thread 1 has already sent the signal with notify_one(). Without it,
thread 2 might lock and wait() after thread 1 has already called
notify_one(), resulting in an indefinite hang since thread 2 is waiting
for something that's already happened.
I've seen lots of code like this where something like cv_flag is used
solely to detect potentially missed signals.
Is this really the only way to do this? And the cleanest and simplest? I
think it would be great if something like:
std::mutex mutex;
std::condition_variable cv;
// no more need for cv_flag
void startThread1()
{
std::cout << "thread 1 prints first\n";
cv.notify_one();
}
void startThread2()
{
std::unique_lock<std::mutex> lock(mutex);
cv.wait_unless_already_signaled(lock); // Unfortunately, this function
doesn't exist
std::cout << "thread 2 prints second\n";
}
Is there anything like wait_unless_already_signaled()? If not, is there a
technical reason for it not existing?

No comments:

Post a Comment