2011-10-23 6 views
6

Mi, clase simplificado acortada se ve de la siguiente manera:"anidada" 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); 
} 

me gustaría sincronizar el acceso en m_myVar. Al llamar A::methodB(), el hilo se ejecuta en la cerradura con el mismo mutex dos veces y, obviamente, los bloques en la primera línea de A::methodA()

¿Hay alguna manera de hacer scoped_lock no bloquear la mismo hilo al pasar de nuevo?

Claro, simplemente podría llamar al m_mutex.unlock(). Pero esto liberaría los otros hilos que también estaban esperando en la cerradura, lo cual no es lo que quiero.

¿Alguna idea?

Saludos Tobias

+8

Use un 'boost :: recursive_mutex' en lugar de un' boost :: mutex' – BatchyX

Respuesta

12

Esto es lo que boost::recursive_mutex para ello permite obtener el bloqueo por el mismo hilo sin bloqueo muchas veces. Úselo en lugar de boost::mutex

+1

+1: pareces decir lo obvio: P gracias! – Atmocreations

0

Puede utilizar el trylock en MethodA si el intento no debe obtener el threadid actual y continuar con la ejecución sólo si el ID del tema es el mismo con el que se ejecuta el threadid MethodB.Otherwise si Si el intento tiene éxito, puede continuar con la ejecución normalmente.

+1

Esto parece una condición de carrera a punto de ocurrir. – user786653

+0

Normalmente, la mejor respuesta en mi opinión es el comentario de BatchyX. Pero realmente no veo ninguna condición de carrera aquí. ¿Puedes por favor explicarme? – AlexTheo

+0

Lo siento, con más pensamiento, probablemente tengas razón, se podría hacer que funcione. – user786653

4

Hay varias cosas que puede hacer aquí. Puede usar un mutex recursivo que se puede adquirir varias veces dentro del mismo hilo, o puede dividir methodA en un método privado con la implementación y sin bloqueos y un método público que bloquea y luego llama a la implementación privada. Entonces methodB llamaría a la implementación interna mientras se mantiene el bloqueo. Como el método es privado, usted tiene el control de todos los usos y puede asegurarse de que solo se invoque el método de implementación mientras se mantiene el bloqueo.