C++ std::vector d'indépendant std::threads
Im construction d'un véritable logiciel au moment où j'ai une boucle infinie sur main()
et de threads utilisés pour lire et traiter des données.
L'un des problèmes est de garder un std::vector
de threads en cours d'exécution à envoyer des signaux à eux et à surveiller l'exécution. J'ai donc monté ce code:
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <chrono>
namespace readerThread {
void start(int id)
{
while (1)
{
std::cout << "Reader " << id << " running..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
}
int main()
{
int readers[] = { 1, 2, 3 };
std::vector<std::thread> readerThreads;
for (int &reader : readers)
{
std::thread th(readerThread::start, reader);
readerThreads.push_back(th);
}
while(true)
{
std::cout << "Waiting..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
}
return 0;
}
Il ne marche pas même de compiler, d'obtenir cette erreur:
In file included from /usr/local/include/c++/5.1.0/x86_64-unknown-linux-gnu/bits/c++allocator.h:33:0,
from /usr/local/include/c++/5.1.0/bits/allocator.h:46,
from /usr/local/include/c++/5.1.0/string:41,
from /usr/local/include/c++/5.1.0/bits/locale_classes.h:40,
from /usr/local/include/c++/5.1.0/bits/ios_base.h:41,
from /usr/local/include/c++/5.1.0/ios:42,
from /usr/local/include/c++/5.1.0/ostream:38,
from /usr/local/include/c++/5.1.0/iostream:39,
from main.cpp:1:
/usr/local/include/c++/5.1.0/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::thread; _Args = {const std::thread&}; _Tp = std::thread]':
/usr/local/include/c++/5.1.0/bits/alloc_traits.h:256:4: required from 'static std::_Require<std::allocator_traits<_Alloc>::__has_construct<_Tp, _Args ...> > std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::thread; _Args = {const std::thread&}; _Alloc = std::allocator<std::thread>; std::_Require<std::allocator_traits<_Alloc>::__has_construct<_Tp, _Args ...> > = void]'
/usr/local/include/c++/5.1.0/bits/alloc_traits.h:402:16: required from 'static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::thread; _Args = {const std::thread&}; _Alloc = std::allocator<std::thread>; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]'
/usr/local/include/c++/5.1.0/bits/stl_vector.h:917:30: required from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::thread; _Alloc = std::allocator<std::thread>; std::vector<_Tp, _Alloc>::value_type = std::thread]'
main.cpp:37:30: required from here
/usr/local/include/c++/5.1.0/ext/new_allocator.h:120:4: error: use of deleted function 'std::thread::thread(const std::thread&)'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
In file included from main.cpp:4:0:
/usr/local/include/c++/5.1.0/thread:126:5: note: declared here
thread(const thread&) = delete;
^
Les fils areindependent, donc je n'ai pas besoin d'appeler join
sur le principal programme, ni sur un fil...
Donc, voici mes doutes:
Pourquoi mon code ne compile pas?
Est-ce la bonne façon de stocker le vecteur de threads ?
Merci pour votre aide...
Si vous envisagez d'arrêter de votre demande correctement, vous devez l'appeler
gomons, n'avez pas votre point. join() permettra de maintenir le thread principal d'exécution, et ce n'est pas souhaitée ici...
Vous pouvez également utiliser
join()
avant que le thread de l'objet à détruire. Ou appelez detach()
pour détacher le thread de l'objet. Sinon, vous aurez une terminate()
appel dans le thread destructeur.gomons, n'avez pas votre point. join() permettra de maintenir le thread principal d'exécution, et ce n'est pas souhaitée ici...
Vous pouvez également utiliser
readerThreads.emplace_back(readerThread::start, reader);
, Ce gomons signifie que vous devez soit join()
ou detach()
un thread instance avant son destructeur s'exécute, sinon terminate()
est appelé. Mais votre fils semble très heureux de courir à l'infini, alors ce n'est pas un problème dans l'exemple ci-dessus.OriginalL'auteur Mendes | 2015-06-10
Vous devez vous connecter pour publier un commentaire.
Vous avez besoin d'utiliser quelque chose comme
Cela fera
th
une rvalue, et la cause de la déplacer ctor à être appelé. La copie ctor dethread
était désactivé par la conception (voir Anthony Williams C++ Simultanéité Dans L'Action).OriginalL'auteur Ami Tavory
Permet de pellicule un peu.
Votre code est en train de faire quelque chose que les tentatives d'introduire une
std::thread
.push_back
est le coupable.std::thread
n'est pas copiable - qu'en serait-il dire pour copier un thread?Ainsi les instances de
std::thread
objets sont destinés à être uniques propriétaires. En dehors de la simple confusion, beaucoup de douleur s'ensuivrait.Ils sont, toutefois, des biens meubles.
t1
n'est plus valide fil descripteur, le thread qu'il a été décrit est maintenant détenue part2
.Pour placer de telles choses dans un conteneur, vous pouvez soit utiliser
std::move
oustd::emplace
/std::emplace_back
.Alors que votre code est de mettre l'accent sur cette question en particulier, permettez-moi de souligner que la norme C++ déclare qu'il y a comme une erreur pour un thread destructeur à être invoquée en tant qu'un thread est encore attaché et n'a pas adhéré.
Lorsque principale se termine, t1.~thread() est appelée, qui détecte que le thread est toujours attaché et n'a pas adhéré, ce qui soulève une exception provoque un arrêt de l'accident.
Vous avez besoin soit de
join()
le fil, en attente pour elle de résilier en cours d'exécution, oudetach()
. Vous aurez besoin d'une façon de dire que le thread de s'arrêter si vous souhaitez utiliserjoin()
et si vousdetach()
le programme peut sortir dans le milieu de la thread de faire quelque chose comme de l'écriture de données, etc, vous pouvez introduire un bug grave.Ici, nous utilisons une promesse de laisser le fil de savoir quand il est temps d'arrêter de courir, mais vous pouvez utiliser les variables de condition, signaux, etc, ou même juste une simple
std::atomic<bool> ok_to_run { true };
test pour de faux.OriginalL'auteur kfsone
Une autre variante qui fonctionne est de créer votre objet thread dans le vecteur.push_back appel. Pas besoin d'appeler std::move dans ce cas, parce que sa déjà une rvalue (donc il va être déplacé).
OriginalL'auteur Seth
C'est la garantie que chaque thread va être créé dans le vecteur de stockage. Aucun objet d'octets à copier.
Dans le cas de ce pas la même chose que @Seth suggéré. Mais dans le cas actuel, il est à 99% le même.
OriginalL'auteur kyb