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:
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With