Ivan Ivan - 1 year ago 85
C++ Question

std::condition_variable without a lock

I'm trying to synchonise a set of threads. These threads sleep most of the time, waking up to do their scheduled job. I'm using

for them.

Unfortunately, when I terminate the application threads prevent it from exiting. In C# I can make a thread to be
so that it will be termianted on app exit. It seems to me that equavalint feature is not availabe at C++.

So I decided to use a kind of event indicator, and make the threads to wake up when the app exits. Standard C++11
requires a unique lock, so I cannot use it, as I need both threads to wake up at the same time (they do not share any resources).

Eventually, I decided to use WinApi's
in order to solve the issue.

I there a way to achieve the same behavior using just c++11?

Again, what do I want:

  1. a set of threads are working independently and usually are asleep
    for a particular period (could be different for different threads;

  2. all threds check a variable that is availabe for all of them whether
    it is a time to stop working (I call this variable
    Actually all threads are spinning in loop like this:

    while (IsAlive) {
    // Do work

  3. threads must be able to work simultaneously, not blocking each other;

  4. when the app is closed and event is risen and it makes the thread to
    wake up right now, no matter the timeout;

  5. waken up, it checks the
    and exits.

Answer Source

yes you can do this using standard c++ mechanisms of condition variables, a mutex and a flag of somekind

// Your class or global variables
std::mutex deathLock;
std::condition_variable deathCv;
bool deathTriggered = false;

// Kill Thread runs this code to kill all other threads:
    std::lock_guard<std::mutex> lock(deathLock);
    deathTriggered = true;

// You Worker Threads run this code:
   ... do work

   // Now wait for 1000 milliseconds or until death is triggered:
   std::unique_lock<std::mutex> lock(deathLock);
   deathCv.wait_for(lock, std::chrono::milliseconds(1000), [](){return deathTriggered;});

   // Check for death

Note that this runs correctly in the face of death being triggered before entering the condition. You could also use the return value from wait_for but this way is easier to read imo. Also, whilst its not clear, multiple threads sleeping is fine as the wait_for code internally unlocks the unique_lock whilst sleeping and reacquires it to check the condition and also when it returns.

Finally, all the threads do wake up 'at the same time' as whilst they're serialised in checking the bool flag, this is only for a few instructions then they unlock the lock as they break out of the loop. It would be unnoticeable.