I'm new to the boost library, and it's such an amazing library! Also, I am new to mutexes, so forgive me if I am making a newbie mistake.
Anyway, I have two functions called FunctionOne and FunctionTwo. FunctionOne and FunctionTwo are called asynchronously by a different thread. So here's what happens: In FunctionOne, I lock a global mutex at the beginning of the function and unlock the global mutex at the end of the function. Same thing for FunctionTwo.
Now here's the problem: at times, FunctionOne and FunctionTwo are called less than a few milliseconds apart (not always though). So, FunctionOne begins to execute and half-way through FunctionTwo executes. When FunctionTwo locks the mutex, the entire thread that FunctionOne and FunctionTwo are on is stopped, so FunctionOne is stuck half-way through and the thread waits on itself in FunctionTwo forever. So, to summarize:
Function 1 locks mutex and begins executing code.
Function 2 is called a few ms later and locks the mutex, freezing the thread func 1 and 2 are on.
Now func 1 is stuck half-way through and the thread is frozen, so func 1 never finishes and the mutex is locked forever, waiting for func 1 to finish.
What does one do in such situations? Here is my code:
boost::mutex g_Mutex;
lua_State* L;
// Function 1 is called from some other thread
void FunctionOne()
{
g_Mutex.lock();
lua_performcalc(L);
g_Mutex.unlock();
}
// Function 2 is called from some other thread a few ms later, freezing the thread
// and Function 1 never finishes
void FunctionTwo()
{
g_Mutex.lock();
lua_performothercalc(L);
g_Mutex.unlock();
}
Are these functions intended to be re-entrant, such that FunctionOne will call itself or FunctionTwo while holding the mutex? Or vice versa, with FunctionTwo locking the mutex and then calling FunctionOne/FunctionTwo while the mutex is locked?
If not, then you should not be calling these two functions from the same thread. If you intend FunctionTwo to block until FunctionOne has completed then it is a mistake to have it called on the same thread. That would happen if lua_performcalc ends up calling FunctionTwo. That'd be the only way they could be called on the same thread.
If so, then you need a recursive_mutex. A regular mutex can only be locked once; locking it again from the same thread is an error. A recursive mutex can be locked multiple times by a single thread and is locked until the thread calls unlock an equal number of times.
In either case, you should avoid calling lock and unlock explicitly. If an exception is thrown the mutex won't get unlocked. It's better to use RAII-style locking, like so:
{
boost::recursive_mutex::scoped_lock lock(mutex);
...critical section code...
// mutex is unlocked when 'lock' goes out of scope
}
your description is incorrect. a mutex cannot be locked twice. you have a different problem.
check for reentrance while the mutex is locked.
check for exceptions
to avoid problems with exceptions you should use boost::mutex::scoped_lock (RAAI)
Related
If I want a thread to pause for a while, until certain conditions are met, can I double-lock the mutex?
Here's a basic example of the idea I'm working with right now:
class foo
{
public:
static std::mutex processingMutex;
void infinite_processing_loop()
{
processingMutex.lock(); // Lock the mutex, initially
while(true)
{
if ( /*ready for this thread to process data*/ )
{
// ... perform one round of data processing ...
}
else // NOT ready for this thread to process data
{
/* Pause this thread,
and wait for another thread to unlock this mutex
(when more data might be ready for processing) */
processingMutex.lock();
}
}
processingMutex.unlock(); // Will never be executed
}
};
Will the processing thread halt, when it tries to double-lock the mutex?
And can another thread unlock the same mutex, causing the halted processing thread to resume?
Or does std::mutex automatically recognize when mutex is locked twice from the same processing thread?
std::mutex will usually deadlock on second attempt to lock by the owner thread. And even if it didn't, it's considered a bug for an application to attempt with this primitive.
std::recursive_mutex will allow re-entrant locks. So if you lock twice, you need to unlock twice before the mutex is available for other threads to grab.
There's a school of thought that any design that involves recursively acquiring a mutex after it's already been locked is a design flaw. I'll try to dig up that thread and add it.
I have 2 processes which share a queue which is synchronized by a mutex and conditions. I have the following code in one of my processes.
named_mutex mutex(open_only, "MyMutex");
int main()
{
while(1)
{
scoped_lock <named_mutex> lock(mutex)
//do some processing
}
}
My question is whether the mutex has scope throughout all calls in the while loop or does it need to be acquired each time the while loop starts? What is the scope of the mutex for it to be unlocked? It seems each time at the end of the while loop the mutex is unlocked.
Thanks
It behaves exactly the same as any other local variable within a loop body: It will be created and destroyed once per itereation. In this case it will lock and unlock the mutex once per iteration.
A scoped_lock, as the name suggests, locks a mutex on creation (in its ctor) and unlocks it on deletion (in its dtor).
Since the scope of the lock instance is within the while body, the mutex is locked when the scoped_lock is created, and unlocked whenever the while loop ends: should a break or continue, or even a return statement be found, or simply when the end of the while body is reached, once for each loop.
I have a problem with a deadlock in my code related to the use of condition variables. This is more of a design question than a pure code question. I have no problem actually writing code once I understand the correct design. I have the following scenario:
Thread A waits on a condition variable.
Thread B calls notify_all, and thread A wakes up.
This is of course what I want to happen, and is what does happen when everything works as expected. But sometimes, I get the following scenario instead:
Thread A executes the code right before it begins to wait on the condition variable.
Thread B calls notify_all, thinking that thread A is waiting.
Thread A begins waiting on the condition variable, not realizing that thread B already told it to stop waiting. Deadlock.
What is the best way to resolve this? I can't think of a reliable way to check whether thread A is actually waiting, in order to know when I should call notify_all in thread B. Do I have to resort to timed_lock? I would hate to.
During the period just before Thread A waits on condition variable it must be holding a mutex. The easiest solution is to make sure that Thread B is holding the same mutex at the time it calls notify_all. So something like this:
std::mutex m;
std::condition_variable cv;
int the_condition = 0;
Thread A: {
std::unique_lock<std::mutex> lock(m);
do something
while (the_condition == 0) {
cv.wait(lock);
}
now the_condition != 0 and thread A has the mutex
do something else
} // releases the mutex;
Thread B: {
std::unique_lock<std::mutex> lock(m);
do something that makes the_condition != 0
cv.notify_all();
} // releases the mutex
This guarantees that Thread B only does the notify_all() either before Thread A acquires the mutex or while Thread A is waiting on the condition variable.
The other key here, though, is the while loop waiting for the_condition to become true. Once A has the mutex it should not be possible for any other thread to change the_condition until A has tested the_condition, found it false, and started waiting (thus releasing the mutex).
The point is: what you are really waiting for is for the value of the_condition to become non-zero, the std::condition_variable::notify_all is just telling you that thread B thinks thread A should wake up and retest.
A condition variable must always be associated with a mutex to avoid a race condition created by one thread preparing to wait and another thread which may signal the condition before the first thread actually waits on it resulting in a deadlock. The thread will be perpetually waiting for a signal that is never sent. Any mutex can be used, there is no explicit link between the mutex and the condition variable.
I am currently trying to create a very simple thread pool using std::thread.
In order to maintain threads 'alive' after their given task is done, I associate a std::mutex with each one of them.
The principle is somewhat like this:
// Thread loop
while (1)
{
m_oMutex->lock();
m_oMutex->unlock();
m_bAvailable = false;
m_oTask();
m_bAvailable = true;
}
// ThreadPool function which gives a task to a thread
void runTask(boost::function<void ()> oTask)
{
[...]
m_oThreads[i]->setTask(oTask);
m_oMutexes[i]->unlock(); // same mutex as thread's m_oMutex
m_oMutexes[i]->lock();
}
To find the i, the ThreadPool searches for a thread object with m_bAvailable set to true. It unlocks the corresponding mutex so the thread can lock it and execute its task. The thread unlocks it immediately so the ThreadPool can lock it again so the thread is halted once its task is done.
But the question is, will locks be made in the order the threads ask them? In other words, if a thread does a lock on a mutex, then the ThreadPool unlocks it and locks it again, am I sure that the lock will be given to the thread first? If not, is there a way to ensure it?
No, you cannot guarantee that your thread loop will ever acquire the lock with your example as is. Use a conditional variable to signal to the thread loop that it should awake and take the lock. See std::condition_variable::wait(...).
condition-variable
More on this topic in general can be found here http://en.wikipedia.org/wiki/Condition_variable. If you were using the pthread library, the equivalent call would be pthread_cond_wait in your "Thread loop" and pthread_cond_signal in your runTask function.
I have the following code:
void Func()
{
boost::interprocess::named_mutex someMutex(boost::interprocess::open_or_create, "MyMutex");
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> lock(someMutex);
// ... some stuff happens here
}
and many applications are calling Func. If there is a crash in Func, the mutex isn't released, so I'm considering removing the mutex, by calling boost::interprocess::named_mutex::remove("MyMutex"), if I detect any of my app crashed.
Due to special circumstance, it's actually safe for two threads or processes to enter the protected area at the same time, because the content of Func() only does things for the first application that runs.
I have two questions:
is what I'm planning to do a good idea?
What happens if:
Process A opens the mutex and locks it (the mutex had been created previously)
Process B dies. We detect that and remove the mutex
Process C creates the mutex and locks it
Process A finishes running Func(), and the scoped_lock destructor releases the mutex
Process C finishes running Func(), and the scoped_lock destructor releases the mutex
now do I have a "double released" named_mutex, or did Process A just didn't do anything in the scoped_lock destructor because the named_mutex it locked had already been removed?