"Nested" scoped_lock

2.6k views Asked by At

My shortened, simplified class looks as follows:

class A
{
    public:
    // ...
    methodA();
    methodB();

    protected:
    mutable boost::mutex m_mutex;
    sometype*  m_myVar;
}

A::methodA( int someParam )
{
    boost::mutex::scoped_lock myLock(m_mutex);
    m_myVar->doSomethingElse();
}

A::methodB( int someParam )
{
    boost::mutex::scoped_lock myLock(m_mutex);
    m_myVar->doSomething();
    this->methodA(someParam);
}

I would like to synchronize access on m_myVar. When calling A::methodB(), the thread runs into the lock with the same mutex twice and obviously blocks on the first line of A::methodA()

Is there any way to make scoped_lock not blocking the same thread when passing again?

Sure, I simply could call m_mutex.unlock(). But this would free the other threads waiting on the lock as well - which is absolutely not what I want.

Any idea?

Best regards Tobias

3

There are 3 answers

0
Artyom On BEST ANSWER

This is what boost::recursive_mutex for it allows to obtain the lock by the same thread without deadlocking several times. Use it instead of boost::mutex

4
AlexTheo On

You can use the tryLock in methodA if the try failed you should get the current threadId and continue with execution only if the thread id is the same with threadid which runs the MethodB.Otherwise if the try succeed you can continue with execution normally.

0
David Rodríguez - dribeas On

There are different things that you can do here. You can use a recursive mutex that can be acquired multiple times within the same thread, or you can split methodA into a private method with the implementation and no locks and a public method that locks and then calls the private implementation. Then methodB would call the internal implementation while holding the lock. Because the method is private you have control over all the uses and you can ensure that the implementation method is only called while holding the lock.