Bonjour,
Dans le cadre d'un rojet, je suis amener à utiliser des threads.
J'ai trouvé la librairie Pthread en C, et j'ai vu que l'on pouvait l'adapter à C++.
Existe-t-il d'autres possibilités ? Il faut que mon programme tourne sur Linux.
Merci
Bonjour,
Dans le cadre d'un rojet, je suis amener à utiliser des threads.
J'ai trouvé la librairie Pthread en C, et j'ai vu que l'on pouvait l'adapter à C++.
Existe-t-il d'autres possibilités ? Il faut que mon programme tourne sur Linux.
Merci
pthread est la librairie de thread système ; a ma connaissance, toute autre librairie sera soit basée dessus (comme boost.thread), soit bâtie autour d'un système qui sera très similaire voire identique (comme... comme... mince, je n'ai pas d'exemple).
A noter que gcc sait nativement quoi faire avec pthread.
Il ne sert à rien, à mon humble avis, de vouloir trouver une autre solution : c'est la librairie système, donc autant l'utiliser. Construire un wrapper C++ autour de pthread est relativement simple, et il en existe des tonnes (dont le déjà mentionné boost.thread).
Cf. http://blog.emptycrate.com/node/270 pour une base (relativement) correcte. On peut faire bien mieux, bien sûr.
[FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.
Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.
J'ai commencé un wrapper en m'inspirant fortement de ce que j'ai trouvé ici :
http://blog.nicoleau-fabien.net/inde...ns-un-object-C
Mais j'ai un problème à la déclaration de la structure pthread_t dans mon header :
Et ce que me sors GCC :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 #ifndef PTHREAD_H #define PTHREAD_H #include <pthread.h> //Définition du processus typedef void* (*threadProcess)(void*); //Définition de la structure d'un thread typedef struct { threadProcess process; void *args; bool *running; bool *finished; } threadParams; //////////////////////////////////////////////////////////////////////////// // Librairie utilisant les pthread du C pour faire un objet thread simple // //////////////////////////////////////////////////////////////////////////// class PThread { private: /////////////// // ATTRIBUTS // /////////////// //Handle du thread pthread_t* handle; //S'il est actif bool running; //S'il est fini bool finished; ////////////// // FONCTIONS // /////////////// //Fonction threadée static void* threadStartup(void*); public: //Constructeur PThread(); //Destructeur ~PThread(); //Prparer et lancer un thread bool exec(threadProcess, void*); //Terminer un thread bool terminate(); //Le thread tourne ? bool isRunning(); //Le thread est terminé ? bool isFinished(); //Join le thread void* join(); //Récupérer l'handle du thread pthread_t* getHandle(); }; #endif // PTHREAD_H
Je vous met aussi le cpp :
Code : Sélectionner tout - Visualiser dans une fenêtre à part error: ISO C++ forbids declaration of 'pthread_t' with no type
Merci !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 #include <iostream> #include "../include/PThread.h" using namespace std; /**Constructeur*/ PThread::PThread() { this->finished=false; this->running=false; this->handle=new pthread_t; } /**Destructeur*/ PThread::~PThread() { this->terminate(); pthread_join(*this->handle, NULL); delete this->handle; } /** Prépare et lance un thread. Enregistre la fonction à exécuter et ses arguments, Puis crée un thread et lance la fonction */ bool PThread::exec(threadProcess monThreadProcess, void* args) { //Test si le thread ne tourne pas déjà if(!this->isRunning()) { threadParams tp; tp.process=monThreadProcess; tp.args; tp.running=&this->running; tp.finished=&this->finished; if(pthread_create (this->handle, NULL, PThread::threadStartup, (void*)&tp<0) { return false; } } return false; } /**Fonction threadée. Dans cette fonction, le thread est préparé, et ensuite la fonction à exécuter est lancée*/ void* PThread::threadStartup(void* targs) { threadParams* tp=(threadParams*)targs; bool* running=tp->running; bool* finished=tp->finished; threadProcess process=tp->process; void* args=tp->args; *running=true; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); process(args); *running = false; *finished = true; pthread_exit(0); } /**Arrête le thread */ bool PThread::terminate() { //Si le thread tourne if(this->isRunning()) { if(pthread_cancel (*this->handle)!=0) { return false; } this->running=false; return true; } return false; } /**Donne l'état du thread*/ bool PThread::terminate() { return this->running; } /**Dis si le thread est fini*/ bool PThread::isFinished() { return this->finished; } /**Attends la fin du thread et libère la mémoire*/ void* PThread::join() { void* ret; pthread_join(*this->handle, &ret); return ret; } /**Retourne l'handle d'un thread*/ pthread_t* PThread::getHandle() { return this->handle; }![]()
Nommer tes fichiers exactement comme les nom des API sytème ne me semble pas très malin !!!*
A 1 '_' près tu définissais le define system :
toi : #ifndef PTHREAD_H
pthread de linux : #ifndef _PTHREAD_H
Suivant l'usage que tu veux faire des threads, certaines alternatives plus haut niveau que les pthreads peuvent être intéressants (ou pas). Je pense par exemple à TBB ou à openMP.
Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.
J'ai réussi à regler le problème en changeant le nom de la classe.
En revanche, je n'arrive pas à éxecuter une fonction avec le code suivant :
Le compilateur me sort cette erreur :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 void* process(void*); int main(void) { const unsigned int nbThreads = 5; ThreadSiteMaths* threads[nbThreads]; // Création des threads, puis exécution for(unsigned int i = 0; i<nbThreads; i++) { threads[i] = new ThreadSiteMaths(); threads[i]->exec(process,(void*)i); } // Attente de la fin des threads et libération mémoire for(unsigned int i = 0; i<nbThreads; i++) { threads[i]->join(); delete(threads[i]); } return 0; } // Cette fonction compte de 0 à (<arg>+1)*4 void* process(void* arg) { unsigned int numThread=(unsigned int)arg; unsigned int until = (numThread+1)*4; for(unsigned int i = 0 ; i < until ; i ++) { cout << "Thread " << numThread << " : " << i << endl; sleep(1); } }
En fait, l'erreur vient du cast de void*, il n'y a pas d'autres solutions ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part /home/alchimiste/PTut/PThread/main.cpp|46|erreur: cast from void* to unsigned int loses precision
Merci.
boost::thread ? (futurement std::thread) C'est bien pour dégager quantité de ces problèmes de typage inhérents aux API C.
@Emmanuel, Solaris a un truc à lui pour le threading en plus de pthread dans mes souvenirs.
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Avec boost, ça serait plus simple ?
La prise en main est rapide ?
C'est vrai ; ceci dit, pthread est également dispo sur cette plateforme (et encapsule dans ce cas spécifique la librairie thread de Solaris). La plupart des "vieux Unix propriétaires" (Solaris, SCO Unix, voire d'autres) ont une librairies de thread spécifiques, mais pthread existe pour la plupart de ces plateformes sous la forme d'une librairie d'encapsulation.
Pour plus d'informations sur les librairies disponibles, cf. http://www.humanfactor.com/pthreads/posix-threads.html
[FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.
Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.
Ok merci beaucoup, je vais essayer de me débrouiller.
Mais j'ai toujours ce problème de cast...
Les casts entre types pointeurs et type scalaires sont dangereux (au mieux). Si tu veux stocker un int dans un pointeur, tu peux, au choix :
* utiliser une union:
Ou utiliser, si il est supporté sur ta plateforme, le type intptr_t, qui est un type entier qui garanti sizeof(intptr_t) == sizeof(T*) quelque soit T. intptr_t devrait être intégré dans le standard à venir C++1x, et il existe déjà dans le standard C99 supporté par de nombreux compilateurs, y compris gcc et (partiellement) Visual C++ 2010.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 union thread_param { void* as_pointer; int as_value; }; thread_param tp; tp.as_value = i; threads[i]->exec(process,tp.as_pointer); void* process(void* arg) { thread_param tp; tp.as_pointer = arg; int num_thread = tp.as_value; ... }
Le type est défini dans <stdint.h> (C99) ou dans <cstdint> (dans le namespace std, Visual C++ 2010, versions plus récentes de g++) ou <tr1/cstdint> (g++ 4.3 ; dans le namespace std::tr1).
Et si tu ne trouve intptr_t nulle part, voilà un "petit truc rigolo" :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 namespace bits { template <class T> struct same_size_ptr { static const bool value = (sizeof(T) == sizeof(T*)); }; template <class T> struct inner { typedef typename T::type type; }; template <> struct inner<char> { typedef char type; }; template <> struct inner<short> { typedef short type; }; template <> struct inner<int> { typedef int type; }; template <> struct inner<long> { typedef long type; }; template <> struct inner<long long> { typedef long long type; }; template <> struct inner<unsigned char> { typedef unsigned char type; }; template <> struct inner<unsigned short> { typedef unsigned short type; }; template <> struct inner<unsigned int> { typedef unsigned int type; }; template <> struct inner<unsigned long> { typedef unsigned long type; }; template <> struct inner<unsigned long long> { typedef unsigned long long type; }; template <bool cond, class T1, class T2> struct select { }; template <class T1, class T2> struct select<true,T1,T2> { typedef typename T1::type type; }; template <class T1, class T2> struct select<false,T1,T2> { typedef typename T2::type type; }; template <class T1, class T2> struct helper { typedef typename select< same_size_ptr< typename inner<T1>::type >::value, inner<T1>, inner<T2> >::type type; }; typedef helper< helper< helper< helper< char, short >, int >, long >, long long // ou ton type int64, selon ta plateforme >::type basic_intptr_t; typedef helper< helper< helper< helper< unsigned char, unsigned short >, unsigned int >, unsigned long >, unsigned long long // ou ton type int64, selon ta plateforme >::type basic_uintptr_t; } typedef ::bits::basic_intptr_t my_intptr_t; typedef ::bits::basic_uintptr_t my_uintptr_t;
[FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.
Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Merci à tous pour vos réponses.
FInalement j'utilise pthread directement sans wrapper.
J'ai trouvé la solution à mon cast, il faut en fait déclarer une structure qui contiendra les arguments. Caster de void* vers la structue ne pose alors pas de problèmes.
En espérant que celà puisse aider des gens qui ont eu le même problème que moi.
Merci encore !![]()
Partager