OVH Cloud OVH Cloud

Threads

30 réponses
Avatar
gg
Bonjour,

Je souhaiterais savoir comment peut-on implémenter des threads en C++ de
façon assez simple, et que le tout reste multi-plateforme ?

merci bien,

gg

10 réponses

1 2 3
Avatar
Sylvain
Serge Paccalin wrote on 14/11/2006 21:08:

Oui. Ne pas appeler endthread ou endthreadex() en C++ ; cela provoque
une sortie immédiate de la fonction, donc court-circuite les appels aux
destructeurs des objets locaux...


certes, mais ne pas l'appeler est également non encouragé par MS,
endthread forçant le ménage coté gestionnaire de process.

un meilleur conseil est n'appeler pas endthread n'importe où mais juste
à l'unique sortie propre du thread.

ie:

void threadEntryPoint(void* refCon){
// recover context, param, ..., from refCon
...
// start actual thread job
doIt(...);
//or
myBuiltOrRecoverdInstance->doIt(...);
// system clean-up
endthread();
}

Sylvain.

Avatar
Serge Paccalin
Le mercredi 15 novembre 2006 à 03:51:16, Sylvain a écrit dans
fr.comp.lang.c++ :

Serge Paccalin wrote on 14/11/2006 21:08:

Oui. Ne pas appeler endthread ou endthreadex() en C++ ; cela provoque
une sortie immédiate de la fonction, donc court-circuite les appels aux
destructeurs des objets locaux...


certes, mais ne pas l'appeler est également non encouragé par MS,
endthread forçant le ménage coté gestionnaire de process.


Ce n'est pas ce que je comprends :

<MSDN>
You can call _endthread or _endthreadex explicitly to terminate a
thread; however, _endthread or _endthreadex is called automatically when
the thread returns from the routine passed as a parameter to
_beginthread or _beginthreadex.
</MSDN>

endthead[ex] est appelé automatiquement après la sortie de la fonction
utilisateur. Le nettoyage des ressources système aura lieu de toutes
façons.

un meilleur conseil est n'appeler pas endthread n'importe où mais juste
à l'unique sortie propre du thread.


C'est inutile, donc. Et comme c'est dangereux...

--
___________
_/ _ _`_`_`_) Serge PACCALIN -- sp ad mailclub.net
_L_) Pour bien répondre avec Google, ne pas cliquer
-'(__) « Répondre », mais « Afficher les options »,
_/___(_) puis cliquer « Répondre » (parmi les options).


Avatar
Laurent Pointal
"gg" wrote in message
news:453d1abe$0$25911$
Bonjour,

Je souhaiterais savoir comment peut-on implémenter des threads en C++ de
façon assez simple, et que le tout reste multi-plateforme ?

merci bien,



Pour l'aspect multiplateforme, en attendant une normalisation de l'API
C++ pour le multithreading, vous pouvez aussi regarder du côté des
pthread (posix threads) dont il existe une implémentation pour Win32.

http://sourceware.org/pthreads-win32/


Sinon, pour de l'encapsulation C++, il y a d'autres librairies qui
existent (le gros ACE), la partie omnithread d'OmniORB.

http://www.cs.wustl.edu/~schmidt/ACE.html
http://omniorb.sourceforge.net/


A+

Laurent.


Avatar
James Kanze
Venus²² wrote:
"James Kanze" wrote in message
news:
Venus²² wrote:
"gg" wrote in message
news:453d1abe$0$25911$

Je souhaiterais savoir comment peut-on implémenter des
threads en C++ de façon assez simple, et que le tout reste
multi-plateforme ?


Dans une exemple, vous voyez SecondThreadFunc() est un thread
nous voulons le lancer dans un second thread.

Il a dit multi-plateforme, à ce qu'il me semble. Or, ce que tu


Pour multi-platform, remplacez "beginthreadex()" par "Spawn()"


Je n'ai pas de Spawn() non plus sur les machines que j'utilise
d'habitude. Et je n'ai pas les en-têtes que tu as utilisé non
plus. La seule solution « standard » multi-plateforme que je
connais utilise « pthread_create » et « pthread_join ». Il
marche sur prèsque toutes les plateformes sauf une.
Malheureusement, la plateforme où il ne marche pas, c'est
Windows.

Sinon, il existe pas mal de bibliothèques tièrces pour résoudre
le problème, où le code qui dépend de la plateforme n'est pas
ton problème. Au moins d'implémenter soi-même une telle
bibliothèque, je dirais qu'il faudrait s'en servir. Aujourd'hui,
je dirais même qu'il faudrait préférer celle de Boost, ne
serait-ce que parce que la syntaxe qui sera adoptée dans la
prochaine version de C++ risque de lui être très proche. Donc :

#include <boost/thread.hpp>
#include <iostream>
#include <ostream>

int counter = 0 ;

void
secondThreadFunc()
{
std::cout << "In second thread..." << std::endl ;
while ( counter < 1000000 ) {
++ counter ;
}
}

int
main()
{
std::cout << "Creating second thread..." << std::endl ;
boost::thread thread2( &secondThreadFunc ) ;
thread2.join() ;
std::cout << "counter == " << counter << std::endl ;
return 0 ;
}

(Ça marche aussi bien sous Solaris que sous Linux ou sous
Windows chez moi.)

Note bien qu'on peut se servir de boost::bind comme paramètre de
construction du thread, ce qui veut dire qu'on peut lui passer à
peu près les paramètres qu'on veut -- y compris des pointeurs
ou des références, pour des paramètres out.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
James Kanze
Venus²² wrote:
"Sylvain" wrote in message
news:455a061b$0$27407$
Venus²² wrote on 14/11/2006 13:11:

Dans une exemple, vous voyez SecondThreadFunc() est un thread nous vou lons
le lancer dans un second thread.


par paraphraser James, pas très portable tout cela ...



Je sens, en effet, que j'ai trouvé encore un meilleur victime
que toi:-).

#include <windows.h>


ça commence mal question portabilité.



[...]
void main()




Note que ceci provoque une erreur aussi avec g++ (au moins avec
les options que j'utilise). Chose que la spécification du
langage exige.

Pour la reste, je te fais confiance sur les commentaires
concernantes les fonctions Windows ; je ne les connais pas du
tout, vue que je travaille surtout sous Solaris.

Comme j'ai dit, Spawn() est utilisé sous Windows et sous Linux,


Je n'ai jamais vu Spawn sous Linux. Mais c'est vrai que tant
qu'à faire, si on sait ne pas cibler Windows, on se sert
allegrément de l'interface Posix. (En fait, on vient de me dire
que les threads Posix marche même sous Windows. Mais j'attends
voir pour y croire.)

Si on doit cibler aussi Windows (cas quand même assez fréquent),
ou même sinon, je conseille fortement l'utilisation de
boost::threads. Ce n'est pas parfait (mais c'est toujours mieux
que ACE, qui était la bibliothèque de préférence avant), mais
c'est déjà pas mal -- les faiblesses principales, ce sont la
difficulté de propager une exception à travers le join, et la
risque de se rétrouver accidentalement avec des threads
detachés, quand on ne le voulait pas.

les rest n'est pas important,


Ça, c'est toi. Moi, je travaille encore à 90% sous Solaris.

c'est pour lui montrer quelques choses de
multi-platform.


Sauf que ce que tu as montré est strictement Windows, et ne
marche nulle part ailleurs.

Windows est une part de multiplatform ailleurs.


Certes. Et Boost::threads marche sous Windows aussi.

Il y a aussi Windows.h sous Linux,


Et quoi encore ? Il y a peut-être un package qu'on pourrait
installer pour simuler un environement Windows sous Linux, mais
ce n'est pas installé sur les Linux que je connais.

avez-vous donc les meilleurs exemples pour lui?


J'en ai posté un.

Tu réponds avec 20 jours de rétard, et avec une réponse
complétement à côté des pompes. Et tu sembles étonné qu'on
critique ta réponse.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
James Kanze
Sylvain wrote:
Venus²² wrote on 14/11/2006 19:39:


[...]
si la question est quelles
APIs garantissent la portabilité des threads, la seule réponse est au cune.


Aucune normalisée (bien que... si la porte de pthreads vers
Windows marche, Posix est aussi une norme). Ça changera sans
doute avec la prochaine version de la norme C++.

Sinon, il en existe pas mal de bibliothèques tièrces portables,
au moins entre Windows et les diverses Unix. (S'il faut
supporter aussi VMS ou d'autres, je ne sais pas.) Boost::threads
risque fort d'être à la base de ce qui sera adopté par C++, mais
c'est vrai que l'installation de Boost n'est pas ce qu'il y a de
plus facile ni de plus légère. Sinon, Dominique et Laurent en
ont cité d'autres ; avant Boost, ACE avait le vent en poupe.

Certains autres bibliothèques tièrces fournissent aussi une
gestion portable des threads : OmniORB a déjà été cité, mais je
crois que Qt (ou peut-être wxWidgets) aussi. Si tu utilises une
de ces bibliothèques, évidemment, tu as tout à fait intérêt
d'utiliser leur API de threading aussi.

Il y a aussi Windows.h sous Linux


?!? pour définir tous les (ignobles) define de MS ? et alors, les
librairies que vous avez utilisé ne sont pas dispo. (windows.h ne
définit en soi aucune fonction).


J'imagine qu'il s'agit d'un package d'émulation, pour faciliter
la porte des applications Windows. Mais je ne peux pas en dire
plus, étant donné que ce n'est pas installé sur les Linux
auxquels j'ai accès. Mais j'en serais un peu méfiant (de même
que je suis méfiant des émulations de pthreads sous Windows).
Les philosophies de base sont différentes, ce qui mène souvent à
des problèmes dans l'émulation, ou au minimum, une perte de
performances importantes.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
loufoque

La seule solution « standard » multi-plateforme que je
connais utilise « pthread_create » et « pthread_join ». Il
marche sur prèsque toutes les plateformes sauf une.
Malheureusement, la plateforme où il ne marche pas, c'est
Windows.


pthread existe pour MS Windows aussi.
Il y a même plusieurs implémentations avec différentes licences.

Avatar
Sylvain
Serge Paccalin wrote on 15/11/2006 06:07:

Ce n'est pas ce que je comprends :

<MSDN>
You can call _endthread or _endthreadex explicitly to terminate a
thread; however, _endthread or _endthreadex is called automatically when
the thread returns from the routine passed as a parameter to
_beginthread or _beginthreadex.
</MSDN>


quelle MSDN ?

j'ai notamment (ie montée), la version July 2005:

<quote>
You can call _endthread or _endthreadex explicitly to terminate a
thread; however, _endthread or _endthreadex is called automatically when
the thread returns from the routine passed as a parameter to
_beginthread or _beginthreadex. Terminating a thread with a call to
endthread or _endthreadex helps to ensure proper recovery of resources
allocated for the thread.
</quote>

n'as-tu pas oublié la fin ?

la version 2001, plus en phase avec VC6, indique également:

<quote>
The _endthread and _endthreadex functions terminate a thread created by
_beginthread or _beginthreadex, respectively. You can call _endthread or
_endthreadex explicitly to terminate a thread; however, _endthread or
_endthreadex is called automatically when the thread returns from the
routine passed as a parameter to _beginthread or _beginthreadex.
Terminating a thread with a call to endthread or _endthreadex helps to
ensure proper recovery of resources allocated for the thread.
</quote>

C'est inutile, donc. Et comme c'est dangereux...


c'est une erreur ("dangeureux" ??) de l'appeler n'importe où (au milieu
d'objets construits); c'est pertinent ou juste inutile de l'appeler
proprement en sortie.

Sylvain.

Avatar
James Kanze
Sylvain wrote:
Serge Paccalin wrote on 15/11/2006 06:07:

Ce n'est pas ce que je comprends :

<MSDN>
You can call _endthread or _endthreadex explicitly to terminate a
thread; however, _endthread or _endthreadex is called automatically when
the thread returns from the routine passed as a parameter to
_beginthread or _beginthreadex.
</MSDN>


quelle MSDN ?

j'ai notamment (ie montée), la version July 2005:

<quote>
You can call _endthread or _endthreadex explicitly to terminate a
thread; however, _endthread or _endthreadex is called automatically when
the thread returns from the routine passed as a parameter to
_beginthread or _beginthreadex. Terminating a thread with a call to
endthread or _endthreadex helps to ensure proper recovery of resources
allocated for the thread.
</quote>

n'as-tu pas oublié la fin ?


Est-ce que ça change quelque chose ? Si j'ai bien compris,
c'est un peu comme exit(), mais pour un thread. C'est essentiel
que la fonction soit appelée, mais en retournant de la fonction
principale du thread, elle le sera automatiquement de toute
façon. La seule différence entre l'appeler exprès, et retourner
de la fonction principale, c'est qu'en l'appelant exprès, on
n'execute pas les destructeurs des variables automatiques. Ce
qui n'est pas bien du tout.

C'est exactement le cas d'exit, d'ailleurs. Et il est fortmenet
déconseillé d'appeler exit() en C++.

(Seulement, dans le cas des threads : existe-t-il d'autre
moyens de quitter le thread ?)

[...]
C'est inutile, donc. Et comme c'est dangereux...


c'est une erreur ("dangeureux" ??) de l'appeler n'importe où (au milieu
d'objets construits); c'est pertinent ou juste inutile de l'appeler
proprement en sortie.


Le problème reste les destructeurs des variables automatiques.
S'il n'y a pas de variables automatiques avec un destructeur
non-trivial, que tu l'appelles directement ou que tu retournes
de la fonction ne change rien. S'il y a des variables
automatiques, en revanche, il faut faire gaffe.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Serge Paccalin
Le 15.11.2006 12:58, :
Serge Paccalin wrote on 15/11/2006 06:07:
Ce n'est pas ce que je comprends :

<MSDN>
You can call _endthread or _endthreadex explicitly to terminate a
thread; however, _endthread or _endthreadex is called automatically wh en
the thread returns from the routine passed as a parameter to
_beginthread or _beginthreadex.
</MSDN>


quelle MSDN ?

j'ai notamment (ie montée), la version July 2005:

<quote>
You can call _endthread or _endthreadex explicitly to terminate a
thread; however, _endthread or _endthreadex is called automatically whe n
the thread returns from the routine passed as a parameter to
_beginthread or _beginthreadex. Terminating a thread with a call to
endthread or _endthreadex helps to ensure proper recovery of resources
allocated for the thread.
</quote>

n'as-tu pas oublié la fin ?


La fin ne change rigoureusement rien. Elle décrit ce qui se passe dans
endthread[ex], et il n'y a absolument aucune raison que le comportement
soit différent avec l'appel automatique ou avec un appel manuel.

À chaque fois, c'est « You can call » ; si cela devait provoquer un e
fuite de ressources système de l'oublier, ce serait « You must call » ,
ou, au minimum, « You should call »

C'est inutile, donc. Et comme c'est dangereux...


c'est une erreur ("dangeureux" ??)


Non, pas « dangeureux », « dangereux ». Un risque de fuite mémo ire (un
vrai), c'est dangereux pour moi. Mais j'ai écrit des services Windows
qui devaient tourner plusieurs semaines, c'est pour ça que j'y tiens.

de l'appeler n'importe où (au milieu
d'objets construits); c'est pertinent ou juste inutile de l'appeler
proprement en sortie.


Quand tu écris ça, par exemple :

void __stdcall ThreadFunc(void *pUserData)
{
std::string Msg("Message d'erreur quelconque");

for (unsigned i = 0; i < 50000; ++i)
{
}

_endthreadex(0);
}

tu considères que tu l'appelles proprement en sortie ?

Je pense exactement la même chose que James (endthread() = exit()).

--
___________
_/ _ _`_`_`_) Serge PACCALIN -- sp ad mailclub.net
_L_) Pour bien répondre avec Google, ne pas cliquer
-'(__) « Répondre », mais « Afficher les options »,
_/___(_) puis cliquer « Répondre » (parmi les options).


1 2 3