"Вложенный" scoped_lock

Мой сокращенный, упрощенный класс выглядит следующим образом:

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);
}

Я хотел бы синхронизировать доступ на m_myVar, При звонке A::methodB(), поток встречается с одним и тем же мьютексом дважды и, очевидно, блокируется в первой строке A::methodA()

Есть ли способ сделать scoped_lock не блокировать тот же поток при повторном прохождении?

Конечно, я просто мог позвонить m_mutex.unlock(), Но это освободило бы другие потоки, ожидающие блокировки, а это совсем не то, что я хочу.

Любая идея?

С наилучшими пожеланиями Тобиас

3 ответа

Решение

Это то, что boost::recursive_mutex так как позволяет получить блокировку одним и тем же потоком без блокировки несколько раз. Используйте это вместо boost::mutex

Есть разные вещи, которые вы можете сделать здесь. Вы можете использовать рекурсивный мьютекс, который может быть получен несколько раз в одном потоке, или вы можете разделить methodA в приватный метод с реализацией и без блокировок, и публичный метод, который блокирует и затем вызывает приватную реализацию. затем methodB будет вызывать внутреннюю реализацию, удерживая блокировку. Поскольку метод является частным, вы можете контролировать все его применения и можете гарантировать, что метод реализации вызывается только при удержании блокировки.

Вы можете использовать tryLock в methodA, если попытка не удалась, вы должны получить текущий threadId и продолжить выполнение, только если идентификатор потока совпадает с threadid, который запускает MethodB. В противном случае, если попытка завершится успешно, вы можете продолжить выполнение в обычном режиме.

Другие вопросы по тегам