Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 399
TheWaterProgrammer Avatar asked Oct 02 '18 14:10

TheWaterProgrammer


People also ask

How do you wake up a sleeping thread?

We can wake the thread by calling either the notify() or notifyAll() methods on the monitor that is being waited on. Use notifyAll() instead of notify() when you want to wake all threads that are in the waiting state.

What happens to a thread when it sleeps?

Thread. sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system.

Does sleep block thread?

Sleep method causes the current thread to immediately block for the number of milliseconds or the time interval you pass to the method, and yields the remainder of its time slice to another thread. Once that interval elapses, the sleeping thread resumes execution.

How do you stop sleep in C++?

You could use a timed wait on a condition variable, and have the other thread signal your periodic thread to wake up and die when it's time. Alternately you could poll on a pipe with your sleep as a timeout instead of of sleeping. Then you just write a byte to the pipe and the thread wakes up and can exit.


1 Answers

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

like image 122
Jonathan Wakely Avatar answered Oct 04 '22 16:10

Jonathan Wakely