I have two threads and a flag that gets set by the second thread. I could use an atomic_bool
, but I want to be able to wait* for the flag being set on the first thread. How can I do that?
I can't use a condition_variable
I guess, because if the second thread calls notify_one
before the first thread starts waiting, the thread won't wake up.
Also, checking if the flag has already been set should be reasonably fast. I guess this should be rather simple, but I'm just stuck, so I'm asking here. Thanks in advance.
*Edit: Block of course, not busy-wait. Sorry if that wasn't clear.
With the help of cbreak and Ravadre (comments) I got from here:
int main()
{
std::mutex m;
std::condition_variable cv;
std::thread t([&] {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<std::mutex> lock(m);
cv.wait(lock);
std::cout << "Yay!\n";
});
cv.notify_one();
t.join();
}
Which does not usually terminate at all, to here:
int main()
{
std::mutex m;
std::condition_variable cv;
bool flag = false;
std::thread t([&] {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [&] { return flag; });
std::cout << "Yay!\n";
});
{
std::lock_guard<std::mutex> lock(m);
flag = true;
}
cv.notify_one();
t.join();
}
Which actually does the job, but still seems like a lot of unnecessary overhead. Feel free to post an equivalent but more performant (or more elegant) answer, I'll happily accept it. Please do only use standard-C++11 though, and if not, explain why standard-C++11 cannot do this.
Edit: I also wrote a class safe_flag to encapsulate this (thanks again to cbreak); feel free to suggest any improvements.
class safe_flag
{
mutable std::mutex m_;
mutable std::condition_variable cv_;
bool flag_;
public:
safe_flag()
: flag_(false)
{}
bool is_set() const
{
std::lock_guard<std::mutex> lock(m_);
return flag_;
}
void set()
{
{
std::lock_guard<std::mutex> lock(m_);
flag_ = true;
}
cv_.notify_all();
}
void reset()
{
{
std::lock_guard<std::mutex> lock(m_);
flag_ = false;
}
cv_.notify_all();
}
void wait() const
{
std::unique_lock<std::mutex> lock(m_);
cv_.wait(lock, [this] { return flag_; });
}
template <typename Rep, typename Period>
bool wait_for(const std::chrono::duration<Rep, Period>& rel_time) const
{
std::unique_lock<std::mutex> lock(m_);
return cv_.wait_for(lock, rel_time, [this] { return flag_; });
}
template <typename Rep, typename Period>
bool wait_until(const std::chrono::duration<Rep, Period>& rel_time) const
{
std::unique_lock<std::mutex> lock(m_);
return cv_.wait_until(lock, rel_time, [this] { return flag_; });
}
};
bool go = false;
std::mutex mtx;
std::condition_variable cnd;
// waiting thread:
std::unique_lock<std::mutex> lck(mtx);
while (!go)
cnd.wait(lock);
// when we get here we know that go is true, and we have the lock
// signalling thread:
{
std::unique_lock<std::mutex> lck(mtx);
go = true;
cnd.notify_one();
}
// now we've released the lock, so the waiting thread will make progress
What exactly is your platform? On posix-compliant platforms we use
sem_t semaphore;
sem_init( &semaphore , 0 , x );
to get a semaphore with initial value of x. Then with
sem_wait(&semaphore ); sem_post(&semaphore);
you can synchronize the two threads. Remember to declare semaphore
as a global variable to make sure both threads can access it (or by any other means that achieve the same).
So long story short, you can:
sem_t semaphore;
sem_init(&semaphore, 0 , 0 );
void thread2(){
sem_post(&semaphore); //second thread --A
}
void thread1(){
sem_wait(&semaphore); // wait until thread2() executes line A
}
There should be similar utilities to achieve the same on Win32 too.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.