Extraneous call to unlock on scoped_lock - c++

In the following blogpost:
http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
There is a 'push' method defined as follows:
void push(Data const& data)
{
boost::mutex::scoped_lock lock(the_mutex);
the_queue.push(data);
lock.unlock();
the_condition_variable.notify_one();
}
My questions are:
why is there an explicit 'lock.unlock()' being called upon the scoped_lock variable?
What is its purpose?
Can it be safely removed, resulting in the 'notify_one' method call be within the scope of the scoped_mutex?

The unlock is not necessary. It might reduce the time that the mutex is locked for slightly, however.
Keeping it or removing it will not affect thread safety or result in deadlocks.
EDIT: As the article mentions, however, leaving the unlock in there can result in less contention on the mutex. You might as well leave it in. Alternatively, use scope around the mutex, which I personally find highlights the scope of the mutex better if glancing at the code.

The explicit lock is so the that waiting thread isn't woken up by the notification only to have to block on the mutex. This is explained earlier in the article that you linked to.
The reason to still use a scoped_lock is to ensure that the mutex is properly unlocked in case the push fails and throws an exception.

Points 1 and 2 can be answered by the principle that you should hold your locks for the least time possible. As soon as the data has been pushed onto the queue, you no longer need to lock it.
You can remove the unlock as you've suggested, at the expense of keeping the lock in place for longer.
Alternatively, the unlock itself can be removed by adding a new scope, like so:
void push(Data const& data)
{
{ // new scope
boost::mutex::scoped_lock lock(the_mutex);
the_queue.push(data);
} // scope ends, lock gets destroyed
the_condition_variable.notify_one();
}

Related

How to properly solve the producer consumer in C++11

I'm trying to solve the producer consumer problem in C++11.
I have an object which holds resources, and multiple threads can
add or consume those resources. My problem is when I try to implement
a "consume when available" method on that object.
Please assume that insert/remove operations are of trivial complexity.
A little explanation of the logic in code.
struct ResourceManager{
std::mutex mux;
std::unique_lock lock{mux};
std::condition_variable bell;
void addResource(/*some Resource*/){
lock.lock();
//add resource
lock.unlock();
bell.notify_one(); //notifies waiting consumer threads to consume
}
T getResource(){
while(true){
lock.lock();
if(/*resource is available*/){
//remove resource from the object
lock.unlock();
return resource;
}else{
//new unique lock mutex object wmux creation
lock.unlock(); //problem line
bell.wait(wmux); //waits until addResource rings the bell
continue;
}
}
}
};
Suppose the following scenario:
-Two threads, T1, T2, call addResource, getResource almost simultaneously.
-T2 locks the mutex, and finds out there are no more resources available,
so it has to block until a new resource is available.
So it unlocks the mutex and sets up the bell waiting.
-T1 runs match faster. When the mutex is unlocked,
it immediately adds the resource, and before T2 sets up the waiting bell,
T1 has already rang the bell, which notifies no one.
-T2 indefinitely waits for the bell to ring, but no further resources are added.
I'm making the assumption that a thread locking a mutex, may be the only one
to unlock it. So if I tried calling bell.wait before unlocking the mutex,
the mutex could never be unlocked.
I'd like to use no time-waiting or multiple times checking solution if possible.
So which way could I solve this problem in C++11?
lock.unlock(); //problem line
bell.wait(wmux); //waits until addResource rings the bell
Yes, this is the problem line, indeed.
To correctly use a condition variable as designed, you do not unlock a mutex before wait()ing on its related condition variable. wait()ing on a condition variable atomically unlocks it for the duration of the wait, and reacquires the mutex once the thread has been notify()-ed. Both the unlock-and-wait, and wake-up-after-being-notified-and-lock, are atomic operations.
Allnotify()s should be issued while the mutex is locked. All wait() are also done while the mutex is fully locked. Given that notify(), as I mentioned, is atomic, this results in all mutex-related operations being atomic and fully sequenced, including managing the resources protected by the mutex, and thread notification via condition variables, which is now protected by a mutex as well.
There are design patterns that can be implemented that notify condition variables without using mutex protection. But they're much harder to implement correctly and still achieve thread-safe semantics. Having all condition variable operations also protected by the mutex, in addition to everything else that the mutex protects, is much simpler to implement.
std::condition_variable::wait needs to be passed a locked std::unique_lock on your mutex. wait will unlock the mutex as part of its operation, and will re-lock it before it returns.
The normal way to use lock guards like std::lock_guard and std::unique_lock is to construct them locally and let their constructor lock your mutex and their destructor unlock it.
Also, you can avoid the external while loop in your original code by providing a predicate to std::condition_variable::wait.
struct ResourceManager {
std::mutex mux;
std::condition_variable bell;
void addResource(T resource)
{
std::lock_guard<std::mutex> lock{mux};
// Add the resource
bell.notify_one();
}
T getResource()
{
std::unique_lock<std::mutex> lock{mux};
bell.wait(lock, [this](){ return resourceIsAvailable(); });
return // the ressource
}
};

How to solve unreleased lock issue in C++

Someone please help me solve deadlock issues in c++ if possible with reference or examples.
Scenario would be like below.
Thread1 is locked by mutex and doing some operation, thread2 and thread3 are in waiting state for thread1 to unlock to access the resource.
Some abort/unexpected thing happened -- thread1 was terminated and didn't get the unlock, thread2 and thread3 are still waiting.
How to save the main thread (mean nothing should happen to main thread) in such situations.
Please throw some light how to solve such issues in c++.
Thanks,
Sheik
Some abort/unexpected thing happened
Use s.th. like std::lock_guard to prevent 'hanging' locks due to exceptions or forgotten/unexpected, but necessary unlock() operations.
The principle is pretty simple and you can easily implement it for any mechanism that uses a pair of methods that correspond together in a 'lock/unlock' manner:
class LockObject // E.g. mutex or alike
{
public:
// ...
void lock();
void unlock();
};
Bind the guard classes constructor to a reference to the lock object's instance and call lock() in the constructor and unlock() in the destructor:
template<typename T>
class LockGuard
{
public:
LockGuard(T& lockObject)
: lockObject_(lockObject)
{
lockObject_.lock();
}
~LockGuard()
{
lockObject_.unlock();
}
private:
T& lockObject_;
};
Use LockGuard like this:
// Some scope providing 'LockObject lockObject'
{ LockGuard<LockObject> lock(lockObject)
// Do s.th. when lockObject is locked
} // Call of lockObject.unlock() is guaranteed at least here, no matter what
// (exception, goto, break, etc.) caused leaving the block's scope.
Generally threads should not terminate unexpectedly. You may try using try/catch blocks. If you still want to free resources when a thread terminates unexpectedly, you may create a monitor thread that waits for the termination of the first thread.
On Windows, you can use something as ::WaitForSingleObject(m_htThread, INFINITE).
Once the 1st thread had been terminated, you may proceed with freeing abandoned locks.
Maybe you'll want to add some flag which indicates if the termination was graceful.
You'll probably also have to remember which thread is locking which object.
As said, I wouldn't recommend using such method, but on extreme cases.
The way to solve deadlocks in any language or platform is always the same.
Always acquire the locks in the same order.
EDIT: However you have misdescribed your problem. This is not a deadlock. A deadlock is a circular chain of locks. This is simply an unreleased lock, i.e. a lock leak. The solution is the same as any other resource leak: don't. In C++ that means releasing resources in destructors, and ensuring that destructors are called. Somehow your thread has terminated without doing that. Find that problem and fix it.

Boost mutex throw error on close for waiting threads

Is there a way to have a boost mutex throw an exception on any waiting threads? I have a problem where an object is deleted but do to the nature of the software library it is possible threads are still waiting at a mutex within the object and a rather nasty exception is thrown when the mutex is closed. I guess I could use a multiple mutex counter but that could cause performance degradation. What I'd like to have happen is the mutex throw an exception on any threads that are waiting when it is closed so that the stack is unrolled. Is there a clean way to do this that is platform-independent?
Such a concept of a mutex that throws when it is destroyed seems innocuous enough, but when it comes time to implement it, it reveals a flaw in how you are thinking about mutexes.
Let's take a look at some example code to get an idea of the pitfalls of such an approach.
Note: Please do not use the code below, it will cause nothing but endless hours of torment and suffering debugging synchronization problems.
class throwing_mutex
{
private:
mutex m_;
condition_variable cv_;
bool destroyed_;
bool locked_;
public:
void lock()
{
std::unique_lock<std::mutex> lock(m_);
cv_.wait(lock, [&]() {return !locked_ || destroyed_;}); // Wait until the mutex is unlocked or destroyed.
if (destroyed_) throw runtime_error("The exception was terminated while waiting.");
locked_ = true;
}
void unlock()
{
std::unique_lock<std::mutex> lock(m_);
locked_ = false;
lock.unlock();
cv_.notify_one();
}
~throwing_mutex()
{
std::unique_lock<std::mutex> lock(m_);
destroyed_ = true;
lock.unlock();
cv_.notify_all(); // Let all waiters know we are dead.
}
};
Upon destruction, everyone waiting on the throwing_mutex will have an exception thrown. But this opens up a pretty big race condition.
We've handled the case where everyone is waiting for the mutex -- they will safely throw. What we have not handled is the case where anyone is on their way to calling lock() but not quite there yet. When they finally get to the point where they can call lock(), the throwing_mutex has already been destroyed. The bug we've just introduced by means of our flawed methodology is called use-after-free. If we are lucky, the error will present itself early and clearly, but sometimes we aren't so lucky and we will be tormented for hours or days. There is no way that our throwing_mutex class can ever solve that problem and any code that would need such a class does not have well thought out ownership semantics.
So, how do we solve this problem if it isn't by means of a mutex that throws? We fix the lifetime of the mutex and the object[s] that are locked by it.
Presumably, this is mutex is a member of a class. If that is the case, it means delaying destruction until everyone who depends on the object is done with it. This is conveyed with the use of a shared_ptr. Without getting into the nitty-gritty of ownership-semantics, that is the best this can be answered. Hopefully I've changed your way of thinking of the problem enough to stray you away from your original plan and toward something that will work more reliably.

Need to mutex-protect (atomic) assignment sought by condition variable?

I understand how to use condition variables (crummy name for this construct, IMO, as the cv object neither is a variable nor indicates a condition). So I have a pair of threads, canonically set up with Boost.Thread as:
bool awake = false;
boost::mutex sync;
boost::condition_variable cv;
void thread1()
{
boost::unique_lock<boost::mutex> lock1(sync);
while (!awake)
cv.wait(lock1);
lock1.unlock(); // this line actually not canonical, but why not?
// proceed...
}
void thread2()
{
//...
boost::unique_lock<boost::mutex> lock2;
awake = true;
lock2.unlock();
cv.notify_all();
}
My question is: does thread2 really need to be protecting the assignment to awake? It seems to me the notify_all() call should be sufficient. If the data being manipulated and checked against were more than a simple "ok to proceed" flag, I see the value in the mutex, but here it seems like overkill.
A secondary question is that asked in the code fragment: Why doesn't the Boost documentation show the lock in thread1 being unlocked before the "process data" step?
EDIT: Maybe my question is really: Is there a cleaner construct than a CV to implement this kind of wait?
does thread2 really need to be protecting the assignment to awake?
Yes. Modifying an object from one thread and accessing it from another without synchronisation gives undefined behaviour. Even if it's just a bool.
For example, on some multiprocessor systems the write might only affect local memory; without an explicit synchronisation operation, other threads might never see the change.
Why doesn't the Boost documentation show the lock in thread1 being unlocked before the "process data" step?
If you unlocked the mutex before clearing the flag, then you might miss another signal.
Is there a cleaner construct than a CV to implement this kind of wait?
In Boost and the standard C++ library, no; a condition variable is flexible enough to handle arbitrary shared state and not particularly over-complicated for this simple case, so there's no particular need for anything simpler.
More generally, you could use a semaphore or a pipe to send a simple signal between threads.
Formally, you definitely need the lock in both threads: if any thread
modifies an object, and more than one thread accesses it, then all
accesses must be synchronized.
In practice, you'll probably get away with it without the lock; it's
almost certain that notify_all will issue the necessary fence or
membar instructions to ensure that the memory is properly synchronized.
But why take the risk?
As to the absense of the unlock, that's the whole point of the scoped
locking pattern: the unlock is in the destructor of the object, so
that the mutex will be unlocked even if an exception passes through.

Boost get multiple locks for the same thread

I have a basic sample which needs review (C++).
Let's say I have a function PublicFunc(), and another one called PrivateFunc(). I'd like to synchronize them carefully. But PrivateFunc can sometimes call PublicFunc as well what means we are calling it from the same thread. This causes blocks, and I'd like to solve it.
mutable boost::mutex m;
void PublicFunc() {
m.lock();
//Here it blocks, but why?
//What I need is to get the lock if this func was called from PrivateFunc(), so exactly from the same thread.
//But! It should definitely block on calling PublicFunc from outside while we are for example in the 'OtherPrivateFunc'.
//Do some stuff
//this is not necessary
m.unlock();
}
void PrivateFunc() {
m.lock();
PublicFunc();
OtherPrivateFunc();
m.unlock();
}
Which mutex or lock is the right one from the boost library?
Thank you!
A mutex may only be locked once; any call to lock the mutex while it is locked will block, even if the attempt to lock the mutex is made by the thread that holds the lock on the mutex.
If you want to be able to lock a mutex multiple times on the same thread, use recursive_mutex.
Alternatively, consider reorganizing your code so that you have one set of (private) member functions that assume the mutex is locked, and have all other functions delegate to these. This can make the code clearer and can make it easier to verify that the synchronization is correct.