Je veux utiliser std::atomic_bool
parce que je veux avoir un booléen qui est censé être accessible par différents threads.
C'est une variable membre static
. Le problème est que je veux l'initialiser avec false
comme premier état. Normalement, je le ferais comme ça: std::atomic_bool World::mStopEvent = false;
Mais le problème semble être qu'il ne prend pas false
comme constructeur. Alors, comment suis-je censé initialiser une telle variable? J'utilise VS 2012.
Il s'agit d'un problème connu dans Visual Studio 2012 (connu sous le nom de VC11) , vous devez voter sur l'élément Connect existant afin que Microsoft sache qu'il affecte plus de gens car ils ont différé le correctif.
Salut,
Merci d'avoir signalé ce bogue. Je suis le mainteneur de Microsoft de la STL, et je voulais vous faire savoir que si ce bogue reste actif dans notre base de données, il ne sera pas corrigé dans VC11 RTM (VS 2012 RTM). Tous les bogues sont importants pour nous, mais certains sont plus graves que d'autres et atteignent le sommet de notre file d'attente prioritaire.
Je copie et colle cette réponse sur tous les bogues de connexion actifs de la STL, mais les commentaires laconiques suivants s'appliquent spécifiquement à votre bogue:
- Oui, ces constructeurs nous manquent sur
atomic_bool
,atomic_int
, etc. (atomic<bool>
,atomic<int>
, etc. en ont). 29.5 [atomics.types.generic]/7 dit "Il doit y avoir des types nommés correspondant aux spécialisations intégrales de l'atomique, comme spécifié dans le tableau 145, et un type nomméatomic_bool
correspondant auatomic<bool>
. Chaque type nommé est untypedef
de la spécialisation correspondante ou une classe de base de la spécialisation correspondante. S'il s'agit d'une classe de base, elle doit prendre en charge les mêmes fonctions membres que la spécialisation correspondante. "Ce qui me donne vraiment envie d'utiliser des typedefs (1 type est toujours plus simple que 2 types), mais je devrai voir si cela introduirait tout autre problème.Je ne peux pas promettre quand nous serons en mesure de résoudre ce bogue, mais nous espérons le faire dès que possible (et j'enverrai une autre réponse lorsque cela se produira) - notre première opportunité sera le "hors bande" sortie entre VC11 et VC12 que Herb Sutter a annoncé lors de la conférence GoingNative 2012.
Remarque: Connect ne m'informe pas des commentaires. Si vous avez d'autres questions, veuillez m'envoyer un e-mail.
Stephan T. Lavavej Développeur principal - Bibliothèques Visual C++ [email protected]
Fondamentalement, vous devrez utiliser std::atomic<T>
pour l'instant.
Essaye ça:
atomic_bool my_bool = ATOMIC_VAR_INIT(false);
PROBLÈME:
Vous ne pouvez pas utiliser initialisation de copie , car std::atomic_bool
N'est pas constructible par copie:
std::atomic_bool World::mStopEvent = false; // ERROR!
En fait, ce qui précède équivaut à:
std::atomic_bool World::mStopEvent = std::atomic_bool(false); // ERROR!
Cependant, vous pouvez utiliser l'initialisation directe :
std::atomic_bool World::mStopEvent(false);
À votre guise, vous pouvez choisir d'utiliser des accolades au lieu de parenthèses:
std::atomic_bool World::mStopEvent{false};
BOGUE:
Bien que la copie-initialisation soit illégale quel que soit le compilateur que vous choisissez, il semble que l'implémentation de la bibliothèque standard livrée avec VC11 comporte un bogue qui ne vous permettra pas non plus d'effectuer une initialisation directe.
Alors, comment suis-je censé initialiser une telle variable?
SOLUTION:
Comme solution de contournement possible, vous pouvez fournir une paire d'encapsuleurs getter/setter statiques qui - respectivement - définissent et renvoient la valeur de l'indicateur booléen atomique, mais pas avant de vous assurer qu'il a été initialisé au moins une fois et pas plus d'une fois à la valeur initiale souhaitée d'une manière thread-safe (vous pouvez considérer cela comme une sorte d'initialisation paresseuse):
#include <atomic>
#include <mutex>
struct World
{
static bool is_stop_event_set()
{
std::call_once(mStopEventInitFlag, [] () { mStopEvent = false; });
return mStopEvent;
}
static void set_stop_event(bool value)
{
std::call_once(mStopEventInitFlag, [value] () { mStopEvent = value; });
mStopEvent = value;
}
static std::atomic_bool mStopEvent;
static std::once_flag mStopEventInitFlag;
};
std::atomic_bool World::mStopEvent;
std::once_flag World::mStopEventInitFlag;
Maintenant, au lieu d'accéder directement à mStopEvent
, sa valeur doit être lue via la fonction is_stop_event_set()
:
#include <iostream>
int main()
{
std::cout << World::is_stop_event_set(); // Will return false
}
Que diriez-vous:
std::atomic_bool World::mStopEvent(false);