boost::mutex / Comment faire pour tester si un mutex est verrouillé
Je sais, je sais, le titre de mon message peut paraître provocateur, depuis
boost::mutex purposefuly ne pas exposer de verrouillage /déverrouillage (afin d'éviter les serrures).
Cependant, le coup de pouce de la documentation est assez courte sur ces aspects (pour dire le moins), donc je demande si quelqu'un peut m'aider dans la suite de cas d'utilisation.
Supposons que vous avez une classe Foo, qui a :
- un destructeur qui prend un certain temps pour terminer
- une méthode qui est appelée par un thread distinct, mais ne doit pas être appelée lors de la destruction
class Foo
{
public:
virtual ~Foo()
{
//Time consuming operations here
}
//Method called by a timer belonging to a distinct class
void OnTimer()
{
//Other time consuming stuff. Should not be called during destruction !
}
};
J'ai essayé (sans succès) de mettre en œuvre une version basée sur boost::mutex
//boost::mutex implementation
class Foo
{
public:
Foo()
{
}
virtual ~Foo()
{
{
boost::mutex::scoped_lock lock(mDisposingMutex);
//Time consuming operations here
}
}
//Method called by a timer belonging to a distinct class
void OnTimer()
{
{
//Imaginary code here: mutex::locked() method is private !!!
if ( ! mDisposingMutex.locked())
return;
}
//Other time consuming stuff. Should not be called during destruction !
}
private:
boost::mutex mDisposingMutex;
};
Suis-je totalement faux? Quelqu'un peut-il me dire comment c'est censé être fait avec boost::mutex?
Merci !
Ne pas répondre directement à la question, pouvez-vous annuler l'enregistrement en provoquant la
OnTimer()
appel comme la première étape dans votre destructeur? Accordé, un appel peut toujours venir à travers de manière asynchrone "en même temps", mais il n'est pas encore clair pourquoi cet objet subissant la destruction est toujours une cible pour ces rappels.D'accord, c'est une odeur de code. Je suis toujours intéressé à la réponse. @Seh : Votre commentaire est basé sur le même code de l'odorat. Cependant, je ne peux pas l'annuler directement sans casser l'encapsulation.
Un autre approche à prendre en compte: Oubliez le mutex et de définir un modèle de l'état par le biais de laquelle vous vous déplacez avec des transitions atomiques, à l'instar de la bibliothèque Java de
FutureTask
classe. Définir un énumérés modèle de l'état, y compris ALIVE
, DESTRUCTING
, et DESTRUCTED
(peut-être). Dès l'entrée dans le destructeur, atomiquement modifier l'état de la DESTRUCTION (par l'intermédiaire de la SAE si vous êtes paranoïaque), et (peut-être) changer de DESTRUCTED
à la sortie de l'destructeur. Dans OnTimer()
, seulement faire le travail si l'état est VIVANT. Si vous avez besoin d'exclure le destructeur de départ tout en OnTimer()
est en cours d'exécution, vous avez besoin d'une serrure.
OriginalL'auteur Pascal T. | 2009-12-15
Vous devez vous connecter pour publier un commentaire.
Si vous ne vous engagez à utiliser les
Lockable::lock()
dans le destructeur du corps, vous pourriez avoir votreOnTimer()
fonction de l'utilisationVerrouillable::try_lock()
, et continuer uniquement si la fonction renvoie true. Qui auraOnTimer()
mettre le destructeur en attente siOnTimer()
commence en premier, mais il encore ne résout pas le problème de le destructeur en cours d'exécution, de finition et de libérer le mutex, puisOnTimer()
de départ et de réussir à saisir le mutex.Une telle séquence est probablement dans le domaine du comportement indéfini, mais que la malédiction ne s'arrêtera pas de se produire. À l'aide d'un drapeau de l'etat en plus le mutex -- semblable à ce que j'ai décrit dans mon commentaire ci-dessus, vous permettra de détecter ce dernier cas, arrêter
OnTimer()
de faire quelque chose au-delà de la lecture de l'indicateur. À un certain point, si, c'est juste de mettre des pansements sur le dessus de la Bande-Sida.OriginalL'auteur seh
@Seh : je suis totalement d'accord c'est une odeur de code et je devrais être (et sera) de corriger la cause principale.
Cependant, dans l'espoir d'aider toute personne qui pourrait rencontrer le même problème que moi (j'.e combat avec le coup de pouce doc), j'ai essayé de mettre en œuvre votre suggestion.
Le code ci-dessous maintenant compile correctement (même si l'odeur de code est maintenant très forte)
OriginalL'auteur Pascal T.
mutex::try_lock()
OriginalL'auteur rad