Locking scheme a hack - c++

How's this look:
class HugeHack
{
HugeHack() : m_flag( false ) { }
void Logout( )
{
boost::lock_guard< boost::mutex > lock( m_lock );
m_flag = true;
// do stuff that in a perfect world would be atomic with library call and onLogout
// call a library function that waits for a thread to finish, that thread calls my onLogout() function before it dies
m_flag = false;
}
void onLogout()
{
boost::unique_lock< boost::mutex > l( m_lock, boost::defer_lock_t );
if( ! m_flag )
l.lock();
// do stuff
}
boost::mutex m_lock;
bool m_flag;
};
The flag is true ONLY while Logout is running, Logout legitimately waits for a thread to die that calls onLogout, so unless someone else can call onLogout... (can't be totally sure not my library I'm using - QuickFix)
I'm not sure I'm using the unique lock correctly there, if not, the goal is only to conditionally lock the lock (while maintaining scoped locking semantics).

The problem is that if you read m_flag without locking the mutex, you might see m_flag be false even if in reality it is true, and Logout is in the middle of operation. Locking the mutex issues a memory fence, which is essential to ensure proper memory visibility. And BTW stijn is right - if this is all you are after, you can ditch m_flag and use try_lock instead, like this:
boost::mutex::scoped_try_lock l( m_lock );
if ( l )
// lock succeeded

It sounds like what you want to do is release the lock in Logout at the point you are waiting for the thread to terminate (and call onLogout). So do that instead, then unconditionally take the lock in onLogout.

Related

Lambda Expression returning a bool flag not stopping condition variables wait() function

I have a WorkDispatcher class which holds Worker class objects as properties and launches their function in new threads.
Here is a example:
WorkDispatcher.h:
class WorkDispatcher
{
private:
std::thread m_reconstructionThread;
std::shared_ptr <Reconstruction::RGBDImageModel> m_currentRGBD;
public:
WorkDispatcher();
std::mutex m_rgbdMutex, m_commandMutex;
std::deque<Network::NetworkCommandModel> m_CommandQueue;
std::condition_variable m_RgbConditional, m_CommandConditional;
Reconstruction::SceneReconstructor m_Reconstructor;
void Initialize();
void Work();
void Stop();
};
WorkDispatcher.cpp:
void WorkDispatcher::Work()
{
m_reconstructionThread = std::thread(
&Reconstruction::SceneReconstructor::Reconstruct,
std::ref(m_Reconstructor),
std::ref(m_currentRGBD),
std::ref(m_CommandQueue),
std::ref(m_rgbdMutex),
std::ref(m_RgbConditional),
std::ref(m_commandMutex),
std::ref(m_CommandConditional)
);
}
These functions hold infinite loops and I use the condition variables to wait until work is avaible. For example my Reconstruct function:
void SceneReconstructor::Reconstruct(
std::shared_ptr<RGBDImageModel>& currentImage,
std::deque<Network::NetworkCommandModel> commandQueue,
std::mutex& rgbdMutex,
std::condition_variable& rgbdCond,
std::mutex& commandMutex,
std::condition_variable& commandConditional)
{
while (true)
{
std::unique_lock<std::mutex> rgbdLocker(rgbdMutex);
rgbdCond.wait(rgbdLocker, [this] {return m_QuitReconstructionFlag; });
// Quit flag to break out of loop
if (m_QuitReconstructionFlag)
break;
// do stuff here
}
}
So far so good, however if I want to quit the application I need to quit all of my worker threads. As seen above, for this these classes have a flag to quit, which I uses as follows:
void WorkDispatcher::Stop()
{
// for all worker threads do this
m_Reconstructor.m_QuitReconstructionFlag = true;
if (m_reconstructionThread.joinable())
m_reconstructionThread.join();
}
In theory this should stop the wait() function within a worker threads loop and then break out of the loop with the m_QuitReconstructionFlag, however this doesn't work.
What does work is the following:
remove the lambda from the wait functions
call notify_all() on the condition variables after settings the
quit-flags to true;
This works fine for me, however the question is, why doesn't the lambda work?
why doesn't the lambda work?
It works just fine, by itself.
However, C++ requires complex rules to be followed to properly synchronize multiple execution threads. Just because one execution thread sets a particular variable to a value does not guarantee you, in any way, that other execution threads will see the variable's new value. The synchronization rules govern that behavior.
So, this lambda works just fine. In its own execution thread. But if you want this lambda to observe changes to the value, made by other execution threads, this must be correctly synchronized.
Additionally, if you review your documentation of wait(), you should find a detailed explanation that says that if the condition function evaluates to false, it will not be called again until the condition variable is notified.
What does work is ... call notify_all()
Well, of course. Since wait() requires the condition variable to be notified, before it checks the waited-on condition again, then that's what you must do!
Finally, notifying the condition variable will work correctly in most cases, but, as I mentioned, synchronization rules (of which mutexes and condition variables play an important part of) have some edge cases where this, by itself, will not work. You must follow the following sequence of events strictly in order to have proper synchronization in all edge cases:
Lock the same mutex that another execution thread has locked before waiting on its condition variable.
Notify the condition variable.
Unlock the mutex
You must protect m_QuitReconstructionFlag with the same mutex used by the condition variable wait.
Or it won't work.
When using a condition variable if you do not want to learn about the C++ memory model in extreme detail, you should follow "best practices" that defend you against problems.
The best practices for a condition variable is to bundle up 3 things together.
The condition variable.
A mutex (often mutable).
A state.
Then bundle all 3 of them up behind a single abstraction of some kind.
To change the state:
Lock the mutex
Change the state
Notify the condition variable appropriately
Unlock the mutex
Do not think that the state being atomic means you don't have to lock the mutex.
When you want to wait on the condition variable:
Lock the mutex
Wait, passing a lambda that checks the state.
When exiting wait, you are free to update the state.
Unlock the mutex
In general, use a unique_lock to lock the mutex in all of the above cases, and rely on RAII to unlock it.
What, exactly, the state is, and when you notify, is up to you.
Do not interact with that mutex directly outside of this bundle and api, don't interact with the state directly outside of this bundle and api, and don't interact with the condition variable outside of this bundle and api.
Copy or move data out of the api if needed, don't hold pointers or references or iterators into it.
Your state can have more than just one variable in it. Like, you can have a queue and a bool for shutdown.
For example, suppose you have a queue.
template<class T>
struct cv_queue {
std::optional<T> pop() {
auto l = lock();
cv.wait( l, [&]{ return aborted || !queue.empty(); } );
if (aborted) return {};
auto retval = std::move(queue.front());
queue.pop_front();
return retval;
}
void push( T in ) {
auto l = lock();
queue.push_back( std::move(in) );
cv.notify_one();
}
void abort_everything() {
auto l = lock();
abort = true;
cv.notify_all();
}
bool empty() const {
auto l = lock();
return queue.empty();
}
private:
std::condition_variable cv;
mutable std::mutex m;
std::deque<T> queue;
bool aborted=false;
auto lock() const { return std::unique_lock( m ); }
};
adding pop_wait_for or try_pop isn't hard.
A simple 3-part wrapper around data or whatever isn't hard to write. Making it more generic, in my experience, doesn't add much to it being understandable.
Here the lambda returning true is not the condition to stop waiting, rather the lambda is to account for spurious wake ups. The notify or notify_all function of the conditional_variable is what is used to make the wait quit.
Rather than removing the lambda, you must simply change the stop function to
void WorkDispatcher::Stop()
{
// for all worker threads do this
m_Reconstructor.m_QuitReconstructionFlag = true;
m_RgbConditional.notify_all()
if (m_reconstructionThread.joinable())
m_reconstructionThread.join();
}
from here you can see that the wait with predicate passed to it (wait(predicate)) is equivalent to
if(!predicate())
wait()
Hence when you call Stop(), It sets the predicate to true, so when the thread is woken up wait() returns, and the predicate is checked, if it is true, the wait(predicate) returns.
In the earlier case, the predicate was set to true but the function was not woken up

Why is there no wait function for condition_variable which does not relock the mutex

Consider the following example.
std::mutex mtx;
std::condition_variable cv;
void f()
{
{
std::unique_lock<std::mutex> lock( mtx );
cv.wait( lock ); // 1
}
std::cout << "f()\n";
}
void g()
{
std::this_thread::sleep_for( 1s );
cv.notify_one();
}
int main()
{
std::thread t1{ f };
std::thread t2{ g };
t2.join();
t1.join();
}
g() "knows" that f() is waiting in the scenario I would like to discuss.
According to cppreference.com there is no need for g() to lock the mutex before calling notify_one. Now in the line marked "1" cv will release the mutex and relock it once the notification is sent. The destructor of lock releases it again immediately after that. This seems to be superfluous especially since locking is expensive. (I know in certain scenarios the mutex needs to be locked. But this is not the case here.)
Why does condition_variable have no function "wait_nolock" which does not relock the mutex once the notification arrives. If the answer is that pthreads do not provide such functionality: Why can`t pthreads be extended for providing it? Is there an alternative for realizing the desired behavior?
You misunderstand what your code does.
Your code on line // 1 is free to not block at all. condition_variables can (and will!) have spurious wakeups -- they can wake up for no good reason at all.
You are responsible for checking if the wakeup is spurious.
Using a condition_variable properly requires 3 things:
A condition_variable
A mutex
Some data guarded by the mutex
The data guarded by the mutex is modified (under the mutex). Then (with the mutex possibly disengaged), the condition_variable is notified.
On the other end, you lock the mutex, then wait on the condition variable. When you wake up, your mutex is relocked, and you test if the wakeup is spurious by looking at the data guarded by the mutex. If it is a valid wakeup, you process and proceed.
If it wasn't a valid wakeup, you go back to waiting.
In your case, you don't have any data guarded, you cannot distinguish spurious wakeups from real ones, and your design is incomplete.
Not surprisingly with the incomplete design you don't see the reason why the mutex is relocked: it is relocked so you can safely check the data to see if the wakeup was spurious or not.
If you want to know why condition variables are designed that way, probably because this design is more efficient than the "reliable" one (for whatever reason), and rather than exposing higher level primitives, C++ exposed the lower level more efficient primitives.
Building a higher level abstraction on top of this isn't hard, but there are design decisions. Here is one built on top of std::experimental::optional:
template<class T>
struct data_passer {
std::experimental::optional<T> data;
bool abort_flag = false;
std::mutex guard;
std::condition_variable signal;
void send( T t ) {
{
std::unique_lock<std::mutex> _(guard);
data = std::move(t);
}
signal.notify_one();
}
void abort() {
{
std::unique_lock<std::mutex> _(guard);
abort_flag = true;
}
signal.notify_all();
}
std::experimental::optional<T> get() {
std::unique_lock<std::mutex> _(guard);
signal.wait( _, [this]()->bool{
return data || abort_flag;
});
if (abort_flag) return {};
T retval = std::move(*data);
data = {};
return retval;
}
};
Now, each send can cause a get to succeed at the other end. If more than one send occurs, only the latest one is consumed by a get. If and when abort_flag is set, instead get() immediately returns {};
The above supports multiple consumers and producers.
An example of how the above might be used is a source of preview state (say, a UI thread), and one or more preview renderers (which are not fast enough to be run in the UI thread).
The preview state dumps a preview state into the data_passer<preview_state> willy-nilly. The renderers compete and one of them grabs it. Then they render it, and pass it back (through whatever mechanism).
If the preview states come faster than the renderers consume them, only the most recent one is of interest, so the earlier ones are discarded. But existing previews aren't aborted just because a new state shows up.
Questions where asked below about race conditions.
If the data being communicated is atomic, can't we do without the mutex on the "send" side?
So something like this:
template<class T>
struct data_passer {
std::atomic<std::experimental::optional<T>> data;
std::atomic<bool> abort_flag = false;
std::mutex guard;
std::condition_variable signal;
void send( T t ) {
data = std::move(t); // 1a
signal.notify_one(); // 1b
}
void abort() {
abort_flag = true; // 1a
signal.notify_all(); // 1b
}
std::experimental::optional<T> get() {
std::unique_lock<std::mutex> _(guard); // 2a
signal.wait( _, [this]()->bool{ // 2b
return data.load() || abort_flag.load(); // 2c
});
if (abort_flag.load()) return {};
T retval = std::move(*data.load());
// data = std::experimental::nullopt; // doesn't make sense
return retval;
}
};
the above fails to work.
We start with the listening thread. It does step 2a, then waits (2b). It evaluates the condition at step 2c, but doesn't return from the lambda yet.
The broadcasting thread then does step 1a (setting the data), then signals the condition variable. At this moment, nobody is waiting on the condition variable (the code in the lambda doesn't count!).
The listening thread then finishes the lambda, and returns "spurious wakeup". It then blocks on the condition variable, and never notices that data was sent.
The std::mutex used while waiting on the condition variable must guard the write to the data "passed" by the condition variable (whatever test you do to determine if the wakeup was spurious), and the read (in the lambda), or the possibility of "lost signals" exists. (At least in a simple implementation: more complex implementations can create lock-free paths for "common cases" and only use the mutex in a double-check. This is beyond the scope of this question.)
Using atomic variables does not get around this problem, because the two operations of "determine if the message was spurious" and "rewait in the condition variable" must be atomic with regards to the "spuriousness" of the message.

Query std::mutex for lock state

I have a situation where I'd like to do something like that shown below, but there doesn't seem to be a way of querying the mutex without changing its state. I don't want the someFunctionCalledRepeatedlyFromAnotherThread() to hang around waiting for the mutex to free up if it is locked. It must return immediately after performing some alternative action. I'm guessing this omission is there for safety, as the lock may free up in the time between querying it and the function returning. In my case, bad stuff will not happen if the lock is freed while doSomeAlternativeAction() is happening. The fact I'm in this situation probably means I'm doing something wrong, so how should I change my design?
class MyClass
{
std::mutex initMutex;
public:
void someInitializationFunction()
{
std::lock_guard<std::mutex> lock(initMutex);
// Do some work
}
void someFunctionCalledRepeatedlyFromAnotherThread()
{
if (initMutex.isLocked())
{
doSomeAlternativeAction();
return;
}
// otherwise . . .
std::lock_guard<std::mutex> lock(initMutex);
// carry on with work as usual
}
}
Asking mutex for its state is useless: it may be unlocked now, but by the time you get around to lock it, it may be locked. So it does not have such method.
It does, however, have a method try_lock() which locks it if it is not locked and returns true if it acquired the lock and false otherwise. And std::unique_lock (the more advanced version of std::lock_guard) has option to call it.
So you can do:
void someFunctionCalledRepeatedlyFromAnotherThread()
{
std::unique_lock<std::mutex> lock(initMutex, std::try_to_lock);
if(!lock.owns_lock())
{
doSomeAlternativeAction();
return;
}
// otherwise ... go ahead, you have the lock
}
Sounds like you want to use std::unique_lock instead of std::lock_guard. The try_lock method works similar to the TryEnterCriticalSection on Windows, whereby the function will atomically acquire the lock and return 'true' if it can, or just return 'false' if the lock cannot be acquired (and will not block). Refer to http://msdn.microsoft.com/en-us/library/hh921439.aspx and http://en.cppreference.com/w/cpp/thread/unique_lock/try_lock. Note that unique_lock also has other members available for trying to lock such as try_lock_for and try_lock_until.

Mutex guards: is there any automated protection mechanism for objects?

This scenario always occurs frequently: We have some threads, and a shared object, we need to make sure at any time only one thread can modify that object.
Well, the obvious solution is to use the lock the door-do the job-get out of there idiom. In this situation, I always use POSIX mutexes. For example
pthread_mutex_lock(&this->messageRW); // lock the door
P_Message x = this->messageQueue.front(); // do the job
this->messageQueue.pop();
pthread_mutex_unlock(&this->messageRW); // get out of there
// somewhere else, in another thread
while (true) {
P_Message message;
solver->listener->recvMessage(message);
pthread_mutex_lock(&(solver->messageRW)); // lock the door
solver->messageQueue.push(message); // do the job
pthread_mutex_unlock(&(solver->messageRW)); // get out of there
sem_post(&solver->messageCount);
}
I use messageQueue in so many places in code. So ended up with a lot of lock/unlock pairs which are inelegant. I think there should be a way to declare messageQueue as an object that is supposed to be shared between threads, and then threading API can take care of lock/unlock. I can think of a wrapper class, or something similar. A POSIX-based solution is preferred though other API's (boost threads, or other libraries) are also acceptable.
What would you implement in a similar situation?
Update for future readers
I found this. Will be a part of C++14 I guess.
You can use boost:scoped_lock in this case. As soon as you go out of scope, it unlocks elegantly:
boost::mutex mMutex;//member mutex object defined somewhere
{ //scope operator start
boost::mutex::scoped_lock scopedLock(mMutex);
pthread_mutex_lock(); // scoped lock the door
P_Message x = this->messageQueue.front(); // do the job
this->messageQueue.pop();
} //scope operator end, unlock mutex
// somewhere else, in another thread
while (true) {
P_Message message;
solver->listener->recvMessage(message);
boost::mutex::scoped_lock scopedLock(mMutex); // scoped lock the door
solver->messageQueue.push(message); // do the job
sem_post(&solver->messageCount);
} //scope operator end, unlock mutex
For this I would either subclass (is-a) or include (has-a) the message queue class into another class which forced the use of mutexes.
That's functionally what other languages do such as with the Java synchronized keyword - it modifieds the underlying object to be automatically protected.
It's the message queue itself which should handle the locking
(be atomic), not the calling code. And you need more than just
a mutex, you need a condition as well to avoid race conditions.
The standard idiom would be something like:
class ScopedLock // You should already have this one anyway
{
pthread_mutex_t& myOwned;
ScopedLock( ScopedLock const& );
ScopedLock& operator=( ScopedLock const& );
public:
ScopedLock( pthread_mutex_t& owned )
: myOwned( owned )
{
pthread_mutex_lock( &myOwned );
}
~ScopedLock()
{
pthread_mutex_unlock( &myOwned );
}
};
class MessageQueue
{
std::deque<Message> myQueue;
pthread_mutex_t myMutex;
pthread_cond_t myCond;
public:
MessageQueue()
{
pthread_mutex_init( &myMutex );
pthread_cond_init( &myCond );
}
void push( Message const& message )
{
ScopedLock( myMutex );
myQueue.push_back( message );
pthread_cond_broadcast( &myCond );
}
Message pop()
{
ScopedLock( myMutex );
while ( myQueue.empty() ) {
pthread_cond_wait( &myCond, &myMutex );
}
Message results = myQueue.front();
myQueue.pop_front();
return results;
}
};
This needs more error handling, but the basic structure is
there.
Of course, if you can use C++11, you'ld be better off using the
standard thread primitives. (Otherwise, I'd normally suggest
Boost threads. But if you're already using Posix threads, you
might want to wait to convert until you can use standard
threads, rather than converting twice.) But you'll still need
both a mutex and a condition.

Why is Boost scoped_lock not unlocking the mutex?

I've been using boost::mutex::scoped_lock in this manner:
void ClassName::FunctionName()
{
{
boost::mutex::scoped_lock scopedLock(mutex_);
//do stuff
waitBoolean=true;
}
while(waitBoolean == true ){
sleep(1);
}
//get on with the thread's activities
}
Basically it sets waitBoolean, and the other thread signals that it is done by setting waitBoolean to false;
This doesn't seem to work, however, because the other thread can't get a lock on mutex_ !!
I was assuming that by wrapping the scoped_lock in brackets I would be terminating its lock. This isn't the case? Reading online says that it only gives up the mutex when the destructor is called. Won't it be destroyed when it goes out of that local scope?
Signaling part of code:
while(running_){
boost::mutex::scoped_lock scopedLock(mutex_);
//Run some function that need to be done...
if(waitBoolean){
waitBoolean=false;
}
}
Thanks!
To synchronize two threads use a condition variable. That is the state of the art way to synchronize two threads the way you want :
Using boost, the waiting part is something like :
void BoostSynchronisationPoint::waitSynchronisation()
{
boost::unique_lock<boost::mutex> lock(_mutex);
_synchronisationSent = false;
while(!_synchronisationSent)
{
_condition.wait(lock); // unlock and wait
}
}
The notify part is something like :
void BoostSynchronisationPoint::sendSynchronisation()
{
{
boost::lock_guard<boost::mutex> lock(_mutex);
_synchronisationSent = true;
}
_condition.notify_all();
}
The business with _synchronisationSent is to avoid spurrious wakeups : see wikipedia
The scoped_lock should indeed be released at the end of the scope. However you don't lock the waitBoolean when you're looping on it, suggesting you don't protect it properly other places as well - e.g. where it's set to false, and you'll end up with nasty race conditions.
I'd say you should use a boost::condition_variable to do this sort of things, instead of sleep + thread-unsafe checking.
Also I would suggest to mark as volatile that waitBoolean, however you have to use a condition or even better a barrier.