Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost mutex locking on same thread

Tags:

c++

mutex

boost

lua

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();
}
like image 565
arao6 Avatar asked Dec 21 '22 12:12

arao6


1 Answers

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
}
like image 163
John Kugelman Avatar answered Dec 23 '22 02:12

John Kugelman