I want to create a counter inside a thread, and stop it by changing the value of a boolean.
Here's my code:
#include <unistd.h>
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
using namespace std;
bool _terminateT;
mutex mtx;
condition_variable cv;
void counter()
{
unique_lock<mutex> lock(mtx);
int i(0);
while(!_terminateT)
{
cout<<i<<endl;
i++;
cv.wait(lock);
}
}
int main()
{
_terminateT = false;
thread t(counter);
sleep(4);
{
lock_guard<mutex> lckg(mtx);
_terminateT = true;
}
cv.notify_one();
cout<<"main"<<endl;
t.join();
return 0;
}
The problem is that the loop is blocked by the wait function.
Is there a way to protect the _terminateT variable without blocking the while loop?
For that code you don't need condition variable. A mutex protecting the boolean variable would be enough. It should be locked and unlocked in loop check.
In fact, in that particular example where there is no risk of data race (you are just setting variable from 0 to other value once), you could even skip the mutex and set variable in an unprotected manner - the loop will always terminate, as even if thread runs on other core than main function, its cache will get the correct changed value eventually. Situation would be different if you shared other data between threads.
Related
Executing the same code in main thread wrt a separate one,the condition variable behaves differently
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <thread>
using namespace std;
using namespace std::chrono;
using namespace std::chrono_literals;
void waits()
{
std::mutex mCvMtx;
std::condition_variable mCondVar;
auto now = std::chrono::system_clock::now();
std::unique_lock<std::mutex> lk(mCvMtx);
if(mCondVar.wait_until(lk, now+ 3*1000ms) == cv_status::timeout)
{
cout << "Fire";
}
else
{
cout << "Condition variable notified ";
}
now = std::chrono::system_clock::now();
}
int main()
{
std::thread t1(waits);
t1.join();
return 0;
}
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <thread>
using namespace std;
using namespace std::chrono;
using namespace std::chrono_literals;
int main()
{
std::mutex mCvMtx;
std::condition_variable mCondVar;
auto now = std::chrono::system_clock::now();
std::unique_lock<std::mutex> lk(mCvMtx);
if(mCondVar.wait_until(lk, now+ 3*1000ms) == cv_status::timeout)
{
cout << "Fire";
}
else
{
cout << "Condition variable notified ";
}
now = std::chrono::system_clock::now();
return 0;
}
I cannot understand why in the first example the output results in "Fire" (so the cv was not notified and it waits the time I indicated) while in the second case where I execute the same code in the main thread, the output results in "Condition variable notified", without wait any seconds.
Do you have any explanantion? thanks
It's because of spurious wakeups
Spurious wakeup describes a complication in the use of condition
variables as provided by certain multithreading APIs such as POSIX
Threads and the Windows API.
Even after a condition variable appears to have been signaled from a
waiting thread's point of view, the condition that was awaited may
still be false. One of the reasons for this is a spurious wakeup; that
is, a thread might be awoken from its waiting state even though no
thread signaled the condition variable. For correctness it is
necessary, then, to verify that the condition is indeed true after the
thread has finished waiting. Because spurious wakeup can happen
repeatedly, this is achieved by waiting inside a loop that terminates
when the condition is true
Further read:
C++ Core Guidelines: Be Aware of the Traps of Condition Variables
A condition variable is merely a notification mechanism with no state, so that notifications get lost when there are no waiters and spurious wake-ups unblock it when no notification was emitted.
You must wait for a change in a shared state. E.g.:
std::mutex m;
std::condition_variable c;
// Only ever read or write shared_state when the mutex is locked.
// Otherwise race conditions create a deadlock.
bool shared_state = false;
// Waiting thread.
void wait() {
std::unique_lock<std::mutex> l(m);
while(!shared_state) // Also handles spurious wake ups.
c.wait(l);
// shared_state is true, mutex is locked.
}
// Notifying thread.
void wait() {
{
std::unique_lock<std::mutex> l(m);
shared_state = true;
}
c.notify_one();
}
I did a simple experiment to test that:
Main thread create a sub thread.
Subthread wait main thread to signal the conditional variable.
The main thread sleeps 3 seconds and signals the "cond". Then I expect that sub thread will wake up from "cond_wait" and print.
Code:
#include <pthread.h>
#include <unistd.h>
#include <cassert>
#include <iostream>
using namespace std;
pthread_mutex_t mt;
pthread_cond_t cond;
pthread_t tid;
void* tf(void*arg){
pthread_mutex_lock(&mt);
pthread_cond_wait(&cond, &mt);
cout<<"After main thread sleeps 3 seconds\n";
return NULL;
}
int main(){
assert(0==pthread_mutex_init(&mt,NULL));
pthread_create(&tid,NULL,tf,NULL);
sleep(3);
pthread_cond_signal(&cond);
pthread_join(tid,NULL);//Is 2nd parameter useful?
pthread_cond_destroy(&cond);
return 0;
}
But in fact, the sub thread will print "After main thread sleeps 3 seconds" at once. Where did I get wrong?
Thanks.
Most importantly, since you attached the C++ tag to this question, use the C++ threading features, not the pthread library. You are not guaranteed to always have access to that (for example on windows), whereas std::thread is designed to be cross platform and free from some of the annoyances that come with using the pthread() library's C interface
Second, initialize your variables, C and C APIs are annoying like that. Third, you need to account for spurious wakeups, put a while loop around the condition variable wait, and attach an actual condition to it, for example
while (not_signalled) {
pthread_cond_wait(&cond, &mt);
}
What might be happening is that your thread gets woken up spuriously and then finishes since you don't have a while loop protecting against spurious wakeups
Working C++ code
#include <thread>
#include <iostream>
#include <chrono>
using std::cout;
using std::endl;
std::mutex mtx;
std::condition_variable cv;
bool has_signalled{false};
void th_function() {
// acquire the lock
auto lck = std::unique_lock<std::mutex>{mtx};
// loop to protect against spurious wakeups
while (!has_signalled) {
// sleep
cv.wait(lck);
}
cout << "Thread has been signalled" << endl;
}
int main() {
auto th = std::thread{th_function};
// sleep for 2 seconds
std::this_thread::sleep_for(std::chrono::seconds(2));
// signal and change the variable
{
std::lock_guard<std::mutex> lck{mtx};
has_signalled = true;
}
// signal
cv.notify_one();
th.join();
}
I'm not aware about the Linux threading functions but in Windows you would have to initialize the variable that corresponds to pthread_cond_t cond in Linux.
There is a manpage for a function named pthread_cond_init which seems to do exactly that.
I need an example of using notify_all() method. Because I cannot understand how should it work.
Every waiting thread begins with code like that:
std::unique_lock<std::mutex> lock(mutex);
condition_variable.wait(lock, [](){return SOMETHING;});
At the very beginning, waiting thread needs to acquire a mutex. So if there are more than one waiting thread, rest of them will wait to lock a mutex. So what is the purpose of using notify_all() if waiting threads stuck at locking mutex and do not execute a method wait() at all? These threads will wake up one by one instead of simultaneously.
The mutex guards the internal state of the condition_variable. Calling wait on the condition_variable causes the mutex to be unlocked. So while waiting, threads do not own the mutex.
When the wait completes, the mutex is again (atomically) acquired before the call to wait returns.
The threads are not contending on the mutex, they are contending on the condition itself.
You are free to unlock the lock as soon as you return from wait if you wish. If you want to allow multiple threads to synchronise on a condition, for example, this is how you would do it. You can also use this feature to implement a semaphore.
example:
This code processes things in batches of 10. Note that notify_all() goes after the unlock():
#include <condition_variable>
#include <mutex>
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <vector>
void emit(std::string const& s)
{
static std::mutex m;
auto lock = std::unique_lock<std::mutex>(m);
std::cout << s << std::endl;
}
std::mutex m;
std::condition_variable cv;
int running_count = 0;
void do_something(int i)
{
using namespace std::literals;
auto lock = std::unique_lock<std::mutex>(m);
// mutex is now locked
cv.wait(lock, // until the cv is notified, the mutex is unlocked
[]
{
// mutex has been locked here
return running_count < 10;
// if this returns false, mutex will be unlocked again, but code waits inside wait() for a notify()
});
// mutex is locked here
++running_count;
lock.unlock();
// we are doing work after unlocking the mutex so others can also
// work when notified
emit("running " + std::to_string(i));
std::this_thread::sleep_for(500ms);
// manipulating the condition, we must lock
lock.lock();
--running_count;
lock.unlock();
// notify once we have unlocked - this is important to avoid a pessimisation.
cv.notify_all();
}
int main()
{
std::vector<std::thread> ts;
for (int i = 0 ; i < 200 ; ++i)
{
ts.emplace_back([i] { do_something(i); });
}
for (auto& t : ts) {
if (t.joinable()) t.join();
}
}
Consider the following example:
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <signal.h>
#include <thread>
void sleepy() {
usleep(1.0E15);
}
int main() {
std :: thread sleepy_thread(sleepy);
// Wake it up somehow...?
sleepy_thread.join();
}
Here we have a thread that just sleeps forever. I want to join it, without having to wait forever for it to spontaneously wake from usleep. Is there a way to tell it from the extern "hey man, wake up!", so that I can join it in a reasonable amount of time?
I am definitely not an expert on threads, so if possible don't assume anything.
No, it is not possible using the threads from the standard library.
One possible workaround is to use condition_variable::sleep_for along with a mutex and a boolean condition.
#include <mutex>
#include <thread>
#include <condition_variable>
std::mutex mymutex;
std::condition_variable mycond;
bool flag = false;
void sleepy() {
std::unique_lock<std::mutex> lock(mymutex);
mycond.wait_for( lock,
std::chrono::seconds(1000),
[]() { return flag; } );
}
int main()
{
std :: thread sleepy_thread(sleepy);
{
std::lock_guard<std::mutex> lock(mymutex);
flag = true;
mycond.notify_one();
}
sleepy_thread.join();
}
Alternatively, you can use the Boost.Thread library, which implements the interruption-point concept:
#include <boost/thread/thread.hpp>
void sleepy()
{
// this_thread::sleep_for is an interruption point.
boost::this_thread::sleep_for( boost::chrono::seconds(1000) );
}
int main()
{
boost::thread t( sleepy );
t.interrupt();
t.join();
}
Other answers are saying you can use a timed muted to accomplish this. I've put together a small class using a timed mutex to block the 'sleeping' threads, and release the mutex if you want to 'wake' them early. The standard library provides a function for timed_mutex called try_lock_for which will try to lock a mutex for a period of time, before continuing on anyway (and returning an indication of failure)
This can be encapsulated in a class, like the following implementation, which only allows a single call to wake waiting threads. It could also be improved by including a waitUntil function for waiting until a time series to correspond to the timed_mutex's other timed waiting function, try_lock_until but I will leave that as an exercise to the interested, since it seems a simple modification.
#include <iostream>
#include <mutex>
#include <thread>
#include <chrono>
#include <atomic>
// one use wakable sleeping class
class InterruptableSleeper{
std::timed_mutex
mut_;
std::atomic_bool
locked_; // track whether the mutex is locked
void lock(){ // lock mutex
mut_.lock();
locked_ = true;
}
void unlock(){ // unlock mutex
locked_ = false;
mut_.unlock();
}
public:
// lock on creation
InterruptableSleeper() {
lock();
}
// unlock on destruction, if wake was never called
~InterruptableSleeper(){
if(locked_){
unlock();
}
}
// called by any thread except the creator
// waits until wake is called or the specified time passes
template< class Rep, class Period >
void sleepFor(const std::chrono::duration<Rep,Period>& timeout_duration){
if(mut_.try_lock_for(timeout_duration)){
// if successfully locked,
// remove the lock
mut_.unlock();
}
}
// unblock any waiting threads, handling a situation
// where wake has already been called.
// should only be called by the creating thread
void wake(){
if(locked_){
unlock();
}
}
};
The following code:
void printTimeWaited(
InterruptableSleeper& sleeper,
const std::chrono::milliseconds& duration){
auto start = std::chrono::steady_clock::now();
std::cout << "Started sleep...";
sleeper.sleepFor(duration);
auto end = std::chrono::steady_clock::now();
std::cout
<< "Ended sleep after "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
<< "ms.\n";
}
void compareTimes(unsigned int sleep, unsigned int waker){
std::cout << "Begin test: sleep for " << sleep << "ms, wakeup at " << waker << "ms\n";
InterruptableSleeper
sleeper;
std::thread
sleepy(&printTimeWaited, std::ref(sleeper), std::chrono::milliseconds{sleep});
std::this_thread::sleep_for(std::chrono::milliseconds{waker});
sleeper.wake();
sleepy.join();
std::cout << "End test\n";
}
int main(){
compareTimes(1000, 50);
compareTimes(50, 1000);
}
prints
Begin test: sleep for 1000ms, wakeup at 50ms
Started sleep...Ended sleep after 50ms.
End test
Begin test: sleep for 50ms, wakeup at 1000ms
Started sleep...Ended sleep after 50ms.
End test
Example & Use on Coliru
"Is there a way to tell it from the extern "hey man, wake up!", so that I can join it in a reasonable amount of time?"
No, there's no way to do so according c++ standard mechanisms.
Well, to get your thread being woken, you'll need a mechanism that leaves other threads in control of it. Besides usleep() is a deprecated POSIX function:
Issue 6
The DESCRIPTION is updated to avoid use of the term "must" for application requirements.
This function is marked obsolescent.
IEEE Std 1003.1-2001/Cor 2-2004, item XSH/TC2/D6/144 is applied, updating the DESCRIPTION from "process' signal mask" to "thread's signal mask", and adding a statement that the usleep() function need not be reentrant.
there's no way you could get control of another thread, that's going to call that function.
Same thing for any other sleep() functions even if declared from std::thread.
As mentioned in other answers or comments, you'll need to use a timeable synchronization mechanism like a std::timed_mutex or a std::condition_variable from your thread function.
Just use a semaphore, call sem_timedwait instead of usleep, and call sem_post before calling join
One possible approach:(There are many ways to accomplish..also its not good idea to use sleep in your thread)
///Define a mutex
void sleepy()
{
//try to take mutex lock which this thread will get if main thread leaves that
//usleep(1.0E15);
}
int main()
{
//Init the Mutex
//take mutex lock
std :: thread sleepy_thread(sleepy);
//Do your work
//unlock the mutex...This will enable the sleepy thread to run
sleepy_thread.join();
}
Sleep for a short amount of time and look to see if a variable has changed.
#include <atomic>
#include <unistd.h>
#include <thread>
std::atomic<int> sharedVar(1);
void sleepy()
{
while (sharedVar.load())
{
usleep(500);
}
}
int main()
{
std :: thread sleepy_thread(sleepy);
// wake up
sharedVar.store(0);
}
I found that std::condition_variable is very difficult to use due to spurious wakeups. So sometimes I need to set a flags such as:
atomic<bool> is_ready;
I set is_ready to true before I call notify (notify_one() or notify_all()), and then I wait:
some_condition_variable.wait(some_unique_lock, [&is_ready]{
return bool(is_ready);
});
Is there any reason that I shouldn't just do this: (Edit: Ok, this is really a bad idea.)
while(!is_ready) {
this_thread::wait_for(some_duration); //Edit: changed from this_thread::yield();
}
And if condition_variable had chosen a waiting duration (I don't know whether this is true or not), I prefer choose it myself.
You can code this either way:
Using atomics and a polling loop.
Using a condition_variable.
I've coded it both ways for you below. On my system I can monitor in real time how much cpu any given process is using.
First with the polling loop:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
std::atomic<bool> is_ready(false);
void
test()
{
std::this_thread::sleep_for(std::chrono::seconds(30));
is_ready.store(true);
}
int
main()
{
std::thread t(test);
while (!is_ready.load())
std::this_thread::yield();
t.join();
}
For me this takes 30 seconds to execute, and while executing the process takes about 99.6% of a cpu.
Alternatively with a condition_variable:
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
bool is_ready(false);
std::mutex m;
std::condition_variable cv;
void
test()
{
std::this_thread::sleep_for(std::chrono::seconds(30));
std::unique_lock<std::mutex> lk(m);
is_ready = true;
cv.notify_one();
}
int
main()
{
std::thread t(test);
std::unique_lock<std::mutex> lk(m);
while (!is_ready)
{
cv.wait(lk);
if (!is_ready)
std::cout << "Spurious wake up!\n";
}
t.join();
}
This has the exact same behavior except that during the 30 second execution, the process is taking 0.0% cpu. If you're writing an app that might execute on a battery powered device, the latter is nearly infinitely easier on the battery.
Now admittedly, if you had a very poor implementation of std::condition_variable, it could have the same inefficiency as the polling loop. However in practice such a vendor ought to go out of business fairly quickly.
Update
For grins I augmented my condition_variable wait loop with a spurious wakeup detector. I ran it again, and it did not print out anything. Not one spurious wakeup. That is of course not guaranteed. But it does demonstrate what a quality implementation can achieve.
The purpose of std::condition_variable is to wait for some condition to become true. It is not designed to be just a receiver of a notify. You might use it, for example, when a consumer thread needs to wait for a queue to become non-empty.
T get_from_queue() {
std::unique_lock l(the_mutex);
while (the_queue.empty()) {
the_condition_variable.wait(l);
}
// the above loop is _exactly_ equivalent to the_condition_variable.wait(l, [&the_queue](){ return !the_queue.empty(); }
// now we have the mutex and the invariant (that the_queue be non-empty) is true
T retval = the_queue.top();
the_queue.pop();
return retval;
}
put_in_queue(T& v) {
std::unique_lock l(the_mutex);
the_queue.push(v);
the_condition_variable.notify_one(); // the queue is non-empty now, so wake up one of the blocked consumers (if there is one) so they can retest.
}
The consumer (get_from_queue) is not waiting for the condition variable, they are waiting for the condition the_queue.empty(). The condition variable gives you the way to put them to sleep while they are waiting, simultaneously releasing the mutex and doing so in a way that avoids race conditions where you miss wake ups.
The condition you are waiting on should be protected by a mutex (the one you release when you wait on the condition variable.) This means that the condition rarely (if ever) needs to be an atomic. You are always accessing it from within a mutex.