2011-10-23 4 views
6

Mon raccourci, classe simplifié se présente comme suit:"Nested" 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); 
} 

Je voudrais synchroniser l'accès à m_myVar. Lors de l'appel A::methodB(), le fil passe dans la serrure avec le même mutex deux fois et, évidemment, des blocs sur la première ligne de A::methodA()

Est-il possible de faire scoped_lock ne bloque pas le même fil lors du passage à nouveau? Je pourrais simplement appeler m_mutex.unlock(). Mais cela libérerait aussi les autres threads qui attendent sur la serrure - ce qui n'est absolument pas ce que je veux.

Une idée?

Meilleures salutations Tobias

+8

Utilisez un 'boost :: recursive_mutex' au lieu d'un' boost :: mutex' – BatchyX

Répondre

12

C'est ce que boost::recursive_mutex pour cela permet d'obtenir le verrou par le même filetage sans super-blocage plusieurs fois. Utilisez-le au lieu de boost::mutex

+1

+1: vous semblez dire l'évidence: P merci! – Atmocreations

0

Vous pouvez utiliser le trylock dans methodA si l'essai vous avez échoué devriez obtenir le threadId actuel et continuer à l'exécution que si l'ID de fil est la même chose avec threadid qui exécute le MethodB.Otherwise si l'essai réussit, vous pouvez continuer l'exécution normalement.

+1

Cela semble être une condition de concurrence qui attend de se produire. – user786653

+0

Normalement, la meilleure réponse à mon avis est le commentaire de BatchyX. Mais je ne vois vraiment aucune condition de course ici. Pouvez-vous m'expliquer s'il vous plaît? – AlexTheo

+0

Désolé, avec plus de réflexion vous avez probablement raison, il pourrait être fait pour travailler. – user786653

4

Il y a différentes choses que vous pouvez faire ici. Vous pouvez utiliser un mutex récursif qui peut être acquis plusieurs fois dans le même thread, ou vous pouvez diviser methodA en une méthode privée avec l'implémentation et sans verrous et une méthode publique qui verrouille puis appelle l'implémentation privée. Alors methodB appellerait l'implémentation interne tout en maintenant le verrou. Comme la méthode est privée, vous avez le contrôle sur toutes les utilisations et vous pouvez vous assurer que la méthode d'implémentation est appelée uniquement en maintenant le verrou.