How to wake a std::thread while it is sleeping

  • A+
Category:Languages

I am using C++11 and I have a std::thread which is a class member, and it sends information to listeners every 2 minutes. Other that that it just sleeps. So, I have made it sleep for 2 minutes, then send the required info, and then sleep for 2 minutes again.

// MyClass.hpp class MyClass {      ~MyClass();     RunMyThread();  private:     std::thread my_thread;     std::atomic<bool> m_running; }   MyClass::RunMyThread() {      my_thread = std::thread { [this, m_running] {     m_running = true;     while(m_running) {         std::this_thread::sleep_for(std::chrono::minutes(2));         SendStatusInfo(some_info);     } }}; }  // Destructor ~MyClass::MyClass() {     m_running = false; // this wont work as the thread is sleeping. How to exit thread here? } 

Issue:
The issue with this approach is that I cannot exit the thread while it is sleeping. I understand from reading that I can wake it using a std::condition_variable and exit gracefully? But I am struggling to find a simple example which does the bare minimum as required in above scenario. All the condition_variable examples I've found look too complex for what I am trying to do here.

Question:
How can I use a std::condition_variable to wake the thread and exit gracefully while it is sleeping? Or are there any other ways of achieving the same without the condition_variable technique?

Additionally, I see that I need to use a std::mutex in conjunction with std::condition_variable? Is that really necessary? Is it not possible to achieve the goal by adding the std::condition_variable logic only to required places in the code here?

Environment:
Linux and Unix with compilers gcc and clang.

 


How can I use an std::condition_variable to wake the thread and exit gracefully while it was sleeping? Or are there any other ways of achieving the same without condition_variable technique?

No, not in standard C++ as of C++17 (there are of course non-standard, platform-specific ways to do it, and it's likely some kind of semaphore will be added to C++2a).

Additionally, I see that I need to use a std::mutex in conjunction with std::condition_variable? Is that really necessary?

Yes.

Is it not possible to achieve the goal by adding the std::condition_variable logic only to required places in the code piece here?

No. For a start, you can't wait on a condition_variable without locking a mutex (and passing the lock object to the wait function) so you need to have a mutex present anyway. Since you have to have a mutex anyway, requiring both the waiter and the notifier to use that mutex isn't such a big deal.

Condition variables are subject to "spurious wake ups" which means they can stop waiting for no reason. In order to tell if it woke because it was notified, or woke spuriously, you need some state variable that is set by the notifying thread and read by the waiting thread. Because that variable is shared by multiple threads it needs to be accessed safely, which the mutex ensures.

Even if you use an atomic variable for the share variable, you still typically need a mutex to avoid missed notifications.

This is all explained in more detail in https://github.com/isocpp/CppCoreGuidelines/issues/554

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: