2010-09-27 15 views
2

J'apprends actuellement sur la concurrence en C++ et je suis tombé sur un vecteur de threads, ce que je crois sera possible en C++ 0x. Cependant, mon compilateur actuel ne semble pas avoir une implémentation de conteneurs de déplacement et donc des erreurs sont générées car std::thread::thread(const std::thread&) est supprimé, c'est-à-dire que je ne peux utiliser que l'affectation de constructeur/déplacement avec std::thread.allocateur personnalisé en utilisant le déplacement pour le vecteur de thread

Suis-je raison de penser que je pouvais contourner ce problème en écrivant une coutume allocateur utilisant

void MyAllocator::construct (pointer p, reference val) 
/* should be non-const reference to val because using move constructor? */ 
{ 
    new ((void*)p) T (std::move(val)); 
} 

plutôt que

void allocator::construct (pointer p, const_reference val) 
{ 
    new ((void*)p) T (val); 
} 

? Ou une autre variation sur ce thème (éventuellement en utilisant une surcharge de MyAllocator :: construct). NB: Ceci est principalement destiné à être un exercice éducatif à court terme et un travail assez performant pour jouer avec des filets dans des conteneurs. Je n'utiliserais que MyAllocator dans ce contexte. Cependant, veuillez également me diriger vers toutes les bibliothèques qui pourraient avoir cette implémentation afin que je puisse avoir une idée de la source.

Répondre

2

Si votre compilateur ne fournit pas un mouvement conscient std::vector alors vous devrez écrivez votre propre spécialisation de std::vector<std::thread> plutôt que de simplement fournir un allocateur personnalisé.L'ensemble de l'interface C++ 03 vector repose sur la copie: push_back() copie les éléments dans; resize() initialise les éléments vides avec une copie de l'élément passé en tant que second paramètre (même s'il s'agit de la valeur par défaut T()); resize(), reserve(), insert(), erase() et push_back() vont copier éléments si le vecteur doit être réaffecté, ou des éléments autrement besoin de se déplacer, et ainsi de suite.

C'est un problème si commun que j'ai inclus une telle spécialisation avec mon (commercial) just::thread mise en œuvre de std::thread.

2

La manière la plus simple de contourner le problème consiste à allouer les threads sur le tas et à manipuler les pointeurs.

Vérifiez la bibliothèque Boost Pointer Container: boost::ptr_vector<std::thread> me semble ce que vous cherchez.

0

L'exigence que les conteneurs std prennent uniquement des objets copiables a plus à voir avec les interfaces de conteneur C++ 03 qu'avec l'implémentation de l'allocateur. Par exemple

vector<T> b(100); 
vector<T> a; 
a=b; 
assert(a==b); 

La norme nous a == b assure est vrai. Cependant, si T n'était pas copiable, alors dans le meilleur des cas a = b ne compilera pas, dans le pire a = b est indéfini. En outre,

a.push_back(T()); 

peut provoquer un nouvel espace à allouer, et sous le capot il y a des copies au nouveau stockage sous-jacent de l'ancien.

De plus, rien dans la norme C++ 03 ne dit qu'une implémentation doit réellement appeler allocator.construct, et en fait beaucoup (gcc par exemple) ne le font pas. Le standard C++ 0x ajoute de nouvelles fonctions membres à l'interface du conteneur pour les types mobiles, et clarifie la manière dont des choses comme l'opérateur = se comportent en leur présence.

Voir www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2486.pdf