In this article, we will discuss how to wake up a std::thread while it is sleeping. It is known that a thread can't be exited when it is sleeping. So it is woken up using a command as:
std::condition_variable
Below is the pseudo-code to implement the same:
// Custom Class
struct MyClass {
// Constructor
MyClass()
: my_thread([this]() {
this->thread();
})
{
}
// Destructor
~MyClass()
{
{
std::lock_guard<std::mutex> l(m_);
stop_ = true;
}
c_.notify_one();
my_thread.join();
}
// Function that implements the
// thread
void thread()
{
while (this->wait_for(std::chrono::minutes(2)))
SendStatusInfo(some_info);
}
// Function to returns false when
// the thread is stopped
template <class Duration>
bool wait_for(Duration duration)
{
std::unique_lock<std::mutex> l(m_);
return !c_.wait_for(l, duration, [this]() {
return stop_;
});
}
// Conditions Variable
std::condition_variable c_;
std::mutex m_;
bool stop_ = false;
std::thread my_thread;
};
Below is another example to illustrate the same:
std::promise/std::future
The above command can be used as a simpler alternative to the former method. In this case, a Future is not susceptible to false wakes and doesn't require a mutex for synchronization. Below is the pseudo-code to implement the same:
// Promise Condition
std::promise<void> pr;
// Start the thread
std::thread thr{
[fut = pr.get_future()]{
// Iterate until the condition
// break
while (true){
if (fut.wait_for(std::chrono::minutes(2))
!= std::future_status::timeout) return;
}
}
}
;
// When ready to stop
pr.set_value();
// Join the thread
thr.join();
Below is the program to illustrate the above concepts:
// C++ program to illustrate the waking
// of the thread while it is sleeping
#include <bits/stdc++.h>
using namespace std;
std::deque<int> q;
std::mutex mu;
std::condition_variable cond;
// Function to create the thread 1
void function_1()
{
// Initialize a counter variable
int count = 10;
// Iterate until count is positive
while (count > 0) {
// Mutex
std::unique_lock<mutex> locker(mu);
// Push the current count in
// the dequeue
q.push_front(count);
locker.unlock();
cond.notify_one();
// If there is any waiting thread
// then notify that thread
std::this_thread::sleep_for(
chrono::seconds(1));
// Decrement the count
count--;
}
}
// Function to create the thread 2
void function_2()
{
// Initialize a variable to get
// the data from the deque
int data = 0;
while (data != 1) {
std::unique_lock<mutex> locker(mu);
cond.wait(locker, []() {
return !q.empty();
});
// False Waking of thread
data = q.back();
q.pop_back();
locker.unlock();
// Print the message
cout << "t2 got a value from"
" t1"
<< data << '\n';
}
}
// Driver Code
int main()
{
// Create thread 1
std::thread t1(function_1);
// Create thread 2
std::thread t2(function_2);
// Join the threads
t1.join();
t2.join();
return 0;
}
