Faire une classe C++ un Moniteur (dans la concurrente de sens)
Je veux m'assurer qu'un seul thread à la fois peut exécuter une méthode de ma classe C++. En d'autres termes, la classe se comporter comme un Moniteur.
Est-il un motif, templatized façon de le faire, ou une augmentation de la classe que je peux utiliser? Parce que ma seule idée à ce jour est l'ajout d'une Section Critique de membre, et l'acquérir au début de chaque méthode et de le libérer à la fin (à l'aide de RAII, bien sûr). Mais cela semble très redondant, et je ne peux pas le réutiliser pour une autre classe.
Il est difficile pour moi d'imaginer le faire avec moins de code. Le code nécessaire pour votre solution proposée est d'une ligne pour la classe (le mutex membre), plus une ligne pour chaque fonction. Je ne pense pas que ça va arriver plus petits sans le support de la langue. Est-ce la question? Si oui, la réponse est "C++ n'a pas de support de langue pour la fabrication de moniteurs". 🙂
Pourquoi ne pas simplement utiliser un mutex, il est largement disponible. Inventer votre propre primitives de synchronisation a un talent pour byting mal.
Voir Boost.Thread dans le cas où ce n'était pas assez évident. :-]
Pourquoi ne pas simplement utiliser un mutex, il est largement disponible. Inventer votre propre primitives de synchronisation a un talent pour byting mal.
Voir Boost.Thread dans le cas où ce n'était pas assez évident. :-]
OriginalL'auteur dario_ramos | 2012-09-28
Vous devez vous connecter pour publier un commentaire.
Vous pouvez y parvenir avec une utilisation judicieuse de
operator->
et c++ moderne qui donne pour beaucoup plus propre syntaxe que préalablement accepté réponse:L'idée est que vous utilisez la flèche de l'opérateur pour accéder à l'objet sous-jacent, mais qui renvoie un objet d'assistance qui verrouille et puis déverrouille le mutex autour de votre appel de fonction. Ensuite, grâce à la magie de la langue à plusieurs reprises l'application de
operator->
vous obtenez une référence à l'objet sous-jacent.Utilisation:
threadSafeVector->push_back(0);
fonctionne même si en interne, nous faisons appeloperator->
deux fois, ce qui me fait penser qu'il doit avoir travaillé comme ceci:threadSafeVector->->push_back(0);
. La premièrethreadSafeVector->
renvoie une monitor_helper et puis la deuxième->
appels de l'opérateur-> sur ce moniteur helper.Aussi, je me demande pourquoi ne pas simplement utiliser lock_guard/scope_guard dans
monitor::operator->
et retourner un&m_cl
à partir de là. Est-il une raison pour laquelle vous avez mis en place que d'autres struct?La flèche de l'opérateur en c++ spécial sémantique permettant d'être appliquée à plusieurs reprises lorsque le type de retour de l'appel précédent est un pointeur qui cette réponse utilise. Voir par exemple this pour plus de détails. Quant à votre deuxième point, nous avons besoin de garder un verrou pour la durée de l'appel de la fonction qui est la durée de vie de la spéciale
monitor_helper
struct. Ce n'est pas possible avec une normale de verrouillage.Merci pour le lien de drill-down comportement. Je ne savais pas à ce sujet. Quant à la deuxième partie, ayant un
lock_guard
comme première ligne demonitor::operator->
à faire ce que vous dites - tenue d'un verrou pour la durée de l'appel de la fonction.Aucune il ne. Essayez - le programme d'installation d'un débogueur et placez un point d'arrêt dans le destructeur de la
lock_guard
et la fonction d'appel . Il va prendre le verrou pour aussi longtemps qu'il le faut pour retourner le pointeur, puis déverrouiller avant, il appelle la fonction. Il utilise le fait qu'un temp objet est détruit à la fin de la pleine expression après l'appel de la fonction (ce qui déverrouille la serrure).OriginalL'auteur Mike Vine
D'abord faire contrôler générique de la classe. Avec la puissance du C++11, vous pouvez le faire aussi simple que cela:
Bien sûr
critical_section
mise en œuvre est à vous. Je recommande POSIX ou une augmentation des.Il est prêt à utiliser dès maintenant:
Comme vous pouvez le voir parfois, vous devez explicitement état membre dont la fonction que vous voulez l'appeler - std::vector<> a plus d'un push_back...
Pour les compilateurs qui encore ne prennent pas en charge variadic template - la solution sans-le ci-dessous - j'ai le temps pour un maximum de deux arguments - c'est très gênant si nécessaire, ajouter une fonction à plusieurs arguments:
Une fois, C++ n'a pas de variadic templates 😉 Vous pouvez utiliser des méthodes de remplacement:
operation
avec 0,1,2,3... des arguments au lieu d'un seuloperation
avec un nombre quelconque d'arguments. En supposant que personne n'utilise plus de 10 arguments, il est possible de mettre en place cependant de plus pénible que d'variadic templates...C'est une solution élégante. Je ne pense pas que vous pouvez recommander un livre ou un article qui pourrait expliquer l'utilisation de la variadic templates un peu plus? Je trouve la structure FunctionType<R (Objet::*)(Args...)> dur à comprendre (en particulier l'Objet de:* bits.)
Il y a 3 choses derrière cette solution: variadic templates en.wikipedia.org/wiki/Variadic_template; pointeur sur fonction membre: parashift.com/c++-faq/fnptr-vs-memfnptr-types.html; type de fonction en tant que paramètre de modèle: stackoverflow.com/a/4642127/1463922... je ne recommande pas du tout de livres depuis que je suis juste à l'aide de C++ standard et de recherche sur internet si j'ai besoin de quelques informations, donc peut-être une recherche et si vous n'avez pas trouvé de réponses utiles, demandez des livres bon pour ce sujet...
Je plains de tout non programmeur c++ d'achoppement au hasard à cette question.
OriginalL'auteur PiotrNycz