Not able to set conditional Variable - c++

in the below code I am waiting inside function waitingForWork() on a condition variable, butdoTheCleanUp() is never called.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
std::mutex mtx;
std::condition_variable cv;
bool stop=false;
void stopTheWait()
{
sleep(5);
printf("stopping the wait.. \n\n");
std::lock_guard<std::mutex> lck(mtx);
stop = true;
cv.notify_all();
}
void doTheCleanUp()/* is never called*/ {
printf("clean up... \n\n");
}
void waitingForWork(){
printf("wait for ever... \n\n");
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, []{ return stop;});
doTheCleanUp();
printf("clean Up Done, now end wait... \n\n");
}
int main()
{
printf("in main... \n");
std::unique_lock<std::mutex> lck(mtx);
std::thread t1(stopTheWait);
waitingForWork();
printf("exiting main...\n");
sleep(1);
return 0;
}

main() is locking the std::mutex and then calling waitingForWork() in the same thread, which tries to lock the std::mutex again. This is undefined behavior:
If lock is called by a thread that already owns the mutex, the behavior is undefined: for example, the program may deadlock. An implementation that can detect the invalid usage is encouraged to throw a std::system_error with error condition resource_deadlock_would_occur instead of deadlocking.
There is no good reason for main() to obtain that initial lock, get rid of it:
int main()
{
printf("in main... \n");
//std::unique_lock<std::mutex> lck(mtx); // <-- HERE
std::thread t1(stopTheWait);
waitingForWork();
printf("exiting main...\n");
sleep(1);
return 0;
}
Note that in general, if you must lock a mutex multiple times in the same thread, you need to use std::recursive_mutex instead:
A calling thread owns a recursive_mutex for a period of time that starts when it successfully calls either lock or try_lock. During this period, the thread may make additional calls to lock or try_lock. The period of ownership ends when the thread makes a matching number of calls to unlock.
Also note that you need to call t1.join() or t1.detach() before t1 goes out of scope and is destroyed, otherwise its destructor will abortively terminate the calling process:
If *this has an associated thread (joinable() == true), std::terminate() is called.

You have a bug here:
void waitingForWork(){
printf("wait for ever... \n\n");
std::unique_lock<std::mutex> lck(mtx); // This lock is bad.
// you already locked the
// mutex in main.
//
// locking it again is UB
cv.wait(lck, []{ return stop;}); // Once you enter wait()
// lock will be released
// until you are notified.
doTheCleanUp();
printf("clean Up Done, now end wait... \n\n");
}

Related

Why does using multiple mutex's on the same condition variable crash this code?

In the code below, which I have tried to make minimially verifiable, runs fine and does what it should (print 1,2,3 in order no matter which order I pass in threads). However, if I change m1 to m2 in the line that I have commented in the function third, this code crashes with the message "terminated without an active exception". Why can't I use the same condition variable to lock on two different mutex's at the same time?
#include <functional>
#include <mutex>
#include <condition_variable>
#include <future>
#include <iostream>
void printFirst() {
cout << "1";
}
void printSecond() {
cout << "2";
}
void printThird() {
cout << "3";
}
struct test {
condition_variable c, c2;
int count = 0;
mutex m1,m2;
void first(function<void()> printFirst) {
printFirst();
count++;
c.notify_all();
}
void second(function<void()> printSecond) {
unique_lock<mutex> sL1(m1);
c.wait(sL1,[&]{return count>=1;});
printSecond();
count+=1;
c.notify_all();
}
void third(function<void()> printThird) {
unique_lock<mutex> sL2(m1); //If I make m1, m2, this code crashes
c.wait(sL2,[&]{return count>=2;});
printThird();
}
};
int main() {
test t;
function<void()> printFirstN =[&](){ t.first(printFirst);};
function<void()> printSecondN=[&](){ t.second(printSecond);};
function<void()> printThirdN=[&](){ t.third(printThird);};
std::thread t1(printFirstN);
std::thread t2( printThirdN);
std::thread t3( printSecondN);
t1.join();
t2.join();
t3.join();
}
You can't do it because the C++ standard says you can't.
33.5.3 Class condition_variable [thread.condition.condvar]
void wait(unique_lock& lock);
Requires: lock.owns_lock() is true and lock.mutex() is locked by the
calling thread, and either
(9.1) — no other thread is waiting on this
condition_variable object or
(9.2) — lock.mutex() returns the same
value for each of the lock arguments supplied by all concurrently
waiting (via wait, wait_for, or wait_until) threads.
The second clause imposes a requirement that all execution threads must have the same mutex locked, if they are also blocking on the condition variable.
(The above is for the wait method that takes no additional parameters, the same requirement is repeated for all overloads/variations, including the one that your code uses, which takes a predicate).

Why re-use of mutex of a condition variable will result in deadlock?

I confronted a code here when I was seeking for help of the implementation of std::condition_variable in C++ 11. In the question above, such code can be executed correctly whereas adding the comment line in function void g() results in deadlock occasionally. And I want to know why and the exactly inner mechanism of std::condition_variable::wait()(cpp reference really confuses me). Thanks in advance.
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
std::mutex mtx;
std::condition_variable cv;
void f() {
{
std::unique_lock<std::mutex> lock( mtx );
cv.wait( lock );
}
std::cout << "f()\n";
}
void g() {
// std::unique_lock<std::mutex> lock( mtx ); adding this line will result in
// deadlock.
std::this_thread::sleep_for( std::chrono::seconds(1) );
cv.notify_one();
}
int main() {
for (int i = 1; i <= 100; i++) {
std::cout << i << std::endl;
std::thread t1{ f };
std::thread t2{ g };
t2.join();
t1.join();
}
}
You should associate a condition variable with an actual condition, and also account for spurious wakeups. In your example your code can deadlock if you signal the condition variable first and then proceed to sleep on the condition variable via wait().
So your code should ideally look something like the following, (where if you signal before you sleep on wait(), the changed condition will detect that you shouldn't sleep)
void f() {
{
std::unique_lock<std::mutex> lock( mtx );
while (some_boolean) {
cv.wait( lock );
}
}
std::cout << "f()\n";
}
void g() {
std::unique_lock<std::mutex> lock( mtx );
change_some_boolean();
cv.notify_one();
}
Note that it does not matter whether the lock is held when you call notify_one() in g(). You should however, make sure that you hold the lock when you change_some_boolean().
Creating a thread that runs f() before creating a thread that runs g() does not guarantee that f() will start running before g() does. When g() starts first it grabs the lock, sleeps for one second, then notify's the condition variable. Since nobody is waiting for the condition, that notify has no effect. When g() returns it releases the lock. Then f() gets the lock and calls wait(). Nobody wakes it up, and f() just keeps on waiting. This isn't a deadlock; any thread could still call notify() and wake up f().
The answer is in the example at the link you provide: Condition Variable on cppreference
// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again (see notify_one for details)
lk.unlock();
cv.notify_one();
Your example however, does NOT unlock your local variable prior to using notify_one() when it should. Your g() function should look like this:
void g() {
std::unique_lock<std::mutex> lock( mtx );
std::this_thread::sleep_for( std::chrono::seconds(1) );
lock.unlock();
cv.notify_one();
}

std::condition_variable::notify_all() - I need an example

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();
}
}

Mutexes inside if condition

I have a problem with mutexes...
This is the general structure of my code:
#include <mutex>
std::mutex m;
While(1){
m.lock();
if(global_variable1==1){
//CODE GOES HERE
if (err==error::eof){
cout<<"error!"<<endl;
//should I put a m.unlock() here??
continue;
}
int something=1;
global_variable2=something;
}
m.unlock();
usleep(100000);
}
Basically, I want to change global variable safely, so I think I need to use mutexes. I should only unlock the mutex after that "if(global_variable1==1)" function, but if there is an error, the mutex won't be unlocked.. Can I unlock it before the "continue"? Or is this going mess up with anything else? Can having two unlocks for the same mutex.lock() have a undesired behaviour?
This is why C++ has separate lock and mutex classes: a lock is a handy RAII class that will make sure that your mutex gets unlocked even when exceptions are thrown or some other idiot programmer adds a new return/break/continue into the program. Here's how this program works with std::unique_lock:
#include <mutex>
std::mutex m;
While(1){
std::unique_lock<std::mutex> lock(m);
if(global_variable1==1){
//CODE GOES HERE
if (err==error::eof){
cout<<"error!"<<endl;
continue;
}
int something=1;
global_variable2=something;
}
lock.unlock();
usleep(100000);
}
Do not lock/unlock mutexes manually! Instead use a guard, e.g., std::lock_guard<std::mutex>: the guard will acquire a lock upon construction an release it upon destruction. To limit the time the lock is held, just use a block:
while (true) {
{
std::lock_guard<std::mutex> cerberos(m);
// ...
}
sleep(n);
}

Behavior of condition_variable_any when used with a recursive_mutex?

When using condition_variable_any with a recursive_mutex, will the recursive_mutex be generally acquirable from other threads while condition_variable_any::wait is waiting? I'm interested in both Boost and C++11 implementations.
This is the use case I'm mainly concerned about:
void bar();
boost::recursive_mutex mutex;
boost::condition_variable_any condvar;
void foo()
{
boost::lock_guard<boost::recursive_mutex> lock(mutex);
// Ownership level is now one
bar();
}
void bar()
{
boost::unique_lock<boost::recursive_mutex> lock(mutex);
// Ownership level is now two
condvar.wait(lock);
// Does this fully release the recursive mutex,
// so that other threads may acquire it while we're waiting?
// Will the recursive_mutex ownership level
// be restored to two after waiting?
}
By a strict interpretation of the Boost documentation, I concluded that condition_variable_any::wait will not generally result in the recursive_mutex being acquirable by other threads while waiting for notification.
Class condition_variable_any
template<typename lock_type> void wait(lock_type& lock)
Effects:
Atomically call lock.unlock() and blocks the current thread. The thread will unblock when notified by a call to this->notify_one() or
this->notify_all(), or spuriously. When the thread is unblocked (for
whatever reason), the lock is reacquired by invoking lock.lock()
before the call to wait returns. The lock is also reacquired by
invoking lock.lock() if the function exits with an exception.
So condvar.wait(lock) will call lock.unlock, which in turn calls mutex.unlock, which decreases the ownership level by one (and not necessarily down to zero).
I've written a test program that confirms my above conclusion (for both Boost and C++11):
#include <iostream>
#define USE_BOOST 1
#if USE_BOOST
#include <boost/chrono.hpp>
#include <boost/thread.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/recursive_mutex.hpp>
namespace lib = boost;
#else
#include <chrono>
#include <thread>
#include <condition_variable>
#include <mutex>
namespace lib = std;
#endif
void bar();
lib::recursive_mutex mutex;
lib::condition_variable_any condvar;
int value = 0;
void foo()
{
std::cout << "foo()\n";
lib::lock_guard<lib::recursive_mutex> lock(mutex);
// Ownership level is now one
bar();
}
void bar()
{
std::cout << "bar()\n";
lib::unique_lock<lib::recursive_mutex> lock(mutex);
// Ownership level is now two
condvar.wait(lock); // Does this fully release the recursive mutex?
std::cout << "value = " << value << "\n";
}
void notifier()
{
std::cout << "notifier()\n";
lib::this_thread::sleep_for(lib::chrono::seconds(3));
std::cout << "after sleep\n";
// --- Program deadlocks here ---
lib::lock_guard<lib::recursive_mutex> lock(mutex);
value = 42;
std::cout << "before notify_one\n";
condvar.notify_one();
}
int main()
{
lib::thread t1(&foo); // This results in deadlock
// lib::thread t1(&bar); // This doesn't result in deadlock
lib::thread t2(&notifier);
t1.join();
t2.join();
}
I hope this helps anyone else facing the same dilemma when mixing condition_variable_any and recursive_mutex.
You can fix this design by adding a parameter allowed_unlock_count to every function which operates on the mutex object; there are two types of guarantees that can be made about allowed_unlock_count:
(permit-unlock-depth) allowed_unlock_count represents the depth of permitted unlocking of mutex: the caller allows bar to unlock the mutex allowed_unlock_count times. After such unlocking, no guarantee is made about the state of mutex.
(promise-unlock) allowed_unlock_count represents the depth of locking of mutex: the caller guarantees that unlocking mutex exactly allowed_unlock_count times will allow other threads to grab the mutex object.
These guarantees are pre- and post-conditions of functions.
Here bar depends on (promise-unlock):
// pre: mutex locking depth is allowed_unlock_count
void bar(int allowed_unlock_count)
{
// mutex locking depth is allowed_unlock_count
boost::unique_lock<boost::recursive_mutex> lock(mutex);
// mutex locking depth is allowed_unlock_count+1
// you might want to turn theses loops
// into an a special lock object!
for (int i=0; i<allowed_unlock_count; ++i)
mutex.unlock();
// mutex locking depth is 1
condvar.wait(lock); // other threads can grab mutex
// mutex locking depth is 1
for (int i=0; i<allowed_unlock_count; ++i)
mutex.lock();
// mutex locking depth is allowed_unlock_count+1
}
// post: mutex locking depth is allowed_unlock_count
Called function must explicitly allowed to decrease locking depth by the caller.