Comment puis-je créer un motif singleton thread-safe dans Windows?
J'ai lu à propos de "thread-safe" singleton modèles ici:
http://en.wikipedia.org/wiki/Singleton_pattern#C.2B.2B_.28using_pthreads.29
Et il dit au fond que la seule façon est d'utiliser pthread_once - ce qui n'est pas disponible sur Windows.
Est que le seulement moyen de garantir thread-safe initialisation?
J'ai lu ce fil de discussion sur DONC:
Thread-safe paresseux de la construction d'un singleton en C++
Et semble faire allusion à une atomique au niveau de l'OS de swap et de la fonction de comparaison, ce qui je suppose sur Windows:
http://msdn.microsoft.com/en-us/library/ms683568.aspx
Cela peut-il faire ce que je veux?
Edit: je voudrais paresseux de l'initialisation et de là à être une instance de la classe.
Quelqu'un sur un autre site mentionné à l'aide d'un mondial à l'intérieur d'un espace de noms (et il a décrit un singleton comme un anti-modèle) - comment peut-il être un "anti-modèle"?
Accepté Réponse:
J'ai accepté Josh réponse que je suis à l'aide de Visual Studio 2008 - NB: Pour les futurs lecteurs, si vous n'utilisez pas ce compilateur (ou 2005) - N'utilisez pas la accepté de répondre!!
Edit:
Le code fonctionne bien sauf le retour de l'instruction, j'obtiens une erreur:
error C2440: 'return' : impossible de convertir de 'volatile Singleton *' Singleton *'.
Dois-je modifier la valeur de retour d'être volatile Singleton *?
Edit: Apparemment const_cast<> supprimer de la volatilité de la qualification. Encore merci à Josh.
source d'informationauteur Mark Ingram
Vous devez vous connecter pour publier un commentaire.
Si vous utilisez Visual C++ 2005/2008 vous pouvez utiliser la double vérification de verrouillage modèle, puisque "variables se comportent comme des clôtures". C'est le moyen le plus efficace de mettre en œuvre un paresseux-initialisé singleton.
De MSDN Magazine:
Chaque fois que vous avez besoin d'accéder à l'singleton, il suffit d'appeler GetSingleton(). La première fois qu'elle est appelée, l'statique pointeur est initialisé. Après c'est initialisée, la valeur NULL est à vérifier permettra d'éviter le verrouillage de la simple lecture du pointeur.
NE PAS l'utiliser sur n'importe compilateur, car il n'est pas portable. La norme ne donne aucune garantie sur la façon dont cela va fonctionner. Visual C++ 2005 ajoute explicitement à la sémantique de la volatilité pour rendre cela possible.
Vous aurez à déclarer et initialiser la SECTION CRITIQUE ailleurs dans le code. Mais que l'initialisation est bon marché, donc l'initialisation différée est généralement pas important.
Une façon simple de garantir de la croix-plate-forme de thread-safe de l'initialisation d'un singleton est à effectuer de façon explicite (via un appel à une fonction membre statique sur le singleton) dans le thread principal de votre application avant votre application démarre, les autres threads (ou au moins les autres threads qui aura accès au singleton).
Assurer thread-safe d'accès pour le singleton est ensuite réalisé à la manière habituelle avec les mutex/sections critiques.
Initialisation peut également être réalisé à l'aide d'un mécanisme similaire. L'habituel problème rencontré avec ce que le mutex tenus de fournir thread-safety est souvent initialisé dans le singleton lui-même qui pousse juste le fil problème de sécurité à l'initialisation du mutex/section critique. Une façon de surmonter ce problème est de créer et initialiser un mutex/section critique dans le thread principal de votre application puis la passer à la singleton via un appel à une fonction membre statique. Le poids lourd de l'initialisation du singleton peut alors se produire dans un thread de manière sûre à l'aide de cette pré-initialisé mutex/section critique. Par exemple:
Cependant, il existe de bonnes raisons d'éviter l'utilisation de singletons (et pourquoi ils sont parfois appelés comme anti-modèle):
Une alternative est de faire usage d'une " logique de singleton dans laquelle vous pouvez créer et initialiser une seule instance d'une classe dans le thread principal et de le transmettre aux objets qui l'exigent. Cette approche peut devenir trop compliqué, où il y a de nombreux objets qui vous voulez créer comme des singletons. Dans ce cas, les différents objets peuvent être regroupés dans un seul "Contexte" de l'objet qui est ensuite transmis partout où nécessaire.
Alors que j'aime la solution retenue, je viens de trouver une autre piste prometteuse et pensé que je devrais la partager ici: Un Temps D'Initialisation (Windows)
Vous pouvez utiliser des OS primitives telles que les mutex ou de section critique pour assurer thread-safe initialisation cependant, ce qui entraînera une surcharge à chaque fois que votre singleton pointeur est accessible (en raison de l'acquisition d'un verrou). Il est également non portable.
Il y a une clarification point que vous devez considérer pour cette question. Avez-vous besoin d' ...
Il y a de nombreux exemples sur le web pour mettre en œuvre ces modèles en C++. Voici un Projet De Code De L'Échantillon
La suivante explique comment le faire en C#, mais exactement le même concept s'applique à tout langage de programmation qui permettrait de soutenir le pattern singleton
http://www.yoda.arachsys.com/csharp/singleton.html
Ce que vous devez décider si vous souhaitez l'initialisation tardive ou pas. L'initialisation tardive signifie que l'objet contenue à l'intérieur de l'singleton est créé sur le premier appel
ex :
si cet appel n'est pas fait jusqu'à ce que plus tard, il y a un danger d'une condition de concurrence entre les threads comme expliqué dans l'article. Cependant, si vous mettez
au début de votre code où vous présume qu'il est thread-safe, alors vous n'êtes plus paresseux de l'initialisation, vous aurez besoin d'un peu plus de puissance de traitement au démarrage de votre application. Toutefois, il permettra de résoudre beaucoup de maux de tête au sujet des conditions de course si vous le faites.
Si vous êtes à la recherche pour plus de portable, et une solution plus facile, on pourrait se tourner vers boost.
boost::call_once peut être utilisé pour thread-safe de l'initialisation.
Son assez simple à utiliser, et fera partie de la prochaine C++0x standard.
La question ne nécessite pas le singleton est paresseux construits ou pas.
Depuis de nombreuses réponses supposent que, je suppose que pour la première phrase discuter:
Compte tenu du fait que la langue elle-même n'est pas thread-la sensibilisation, et en plus de la technique d'optimisation, l'écriture d'un portable fiable c++ singleton est très difficile (sinon impossible), voir "C++ et les Dangers de la Double vérification de Verrouillage" de Scott Meyers et Andrei Alexandrescu.
J'ai vu beaucoup de la réponse station de synchronisation de l'objet sur la plate-forme windows en utilisant CriticalSection, mais CriticalSection n'est thread-safe lorsque tous les threads en cours d'exécution sur un processeur unique, aujourd'hui, il n'est probablement pas vrai.
MSDN cite: "Les threads d'un même processus peut utiliser un objet de section critique mutuelle-exclusion de la synchronisation. ".
Et http://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs. 85).aspx
clearify encore plus loin:
Un objet de section critique assure la synchronisation similaire à celle fournie par un objet mutex, sauf qu'une section critique peut être utilisée que par les threads d'un même processus.
Maintenant, si le "lazy-construit" n'est pas une exigence, la solution suivante est à la fois de la croix-module de sécurité et thread-safe, et même portable:
C'est la croix-module de sécurité parce que nous avons utilisée localement dans l'étendue objet statique au lieu de fichier/espace de noms de l'étendue globale de l'objet.
C'est thread-safe, car: X_singleton_helper doit être attribué à la valeur correcte avant d'entrer en principal ou DllMain Il n'est pas paresseux-construit aussi en raison de ce fait), dans cette expression, la virgule est un opérateur, pas de ponctuation.
Utiliser explicitement "extern" ici d'éviter compilateur d'optimiser(de Préoccupations au sujet de Scott Meyers article, le grand ennemi est l'optimiseur.), et aussi faire en statique-analyser tels que l'outil de pc-lint garder le silence. "Avant de la main/DllMain" est Scott meyer appelé "single-threaded de démarrage de la partie" dans "Effective C++ 3ème" article 4.
Cependant, je ne suis pas très sûr de savoir si le compilateur est permis d'optimiser l'appel de la get_X_instance() en fonction de la langue standard, s'il vous plaît commentaire.
Il y a beaucoup de façons de le faire thread-safe Singleton* initialisation sur windows. En fait, certains d'entre eux sont même de la croix-plate-forme. Dans le fil qui vous relie à, ils étaient à la recherche d'un Singleton qui est paresseusement construit en C, qui est un peu plus précis, et peut être un peu plus compliqué à faire, compte tenu de la complexité du modèle de mémoire vous travaillez sous.