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
James Kanze wrote on 15/11/2006 13:25:
Sylvain wrote:

n'as-tu pas oublié la fin ?


Est-ce que ça change quelque chose ?


est-ce que (chez MS) "helps to ensure proper recovery of resources"
change quelque chose ?!?

que veux-tu dire ? que le système est de toute façon en permanence
corrompu ?

Si j'ai bien compris,
c'est un peu comme exit(), mais pour un thread.


oui.

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.


certes, mais où est le retour de la fonction principale du thread??
dans le scheduler du noyo ? (fote volontaire)

ton point revient donc à considérer que l'on a le contrôle sur le
"lanceur de processus"; c'était le cas il y a de très nombreuses années
avec des threads tout-à-la-main sous MacOS (notamment), ce n'est pas le
cas avec ses API hydribes, ni avec le 100% MS.

or endthread doit être appeler par le thread se terminant, par lui-même,
pas un autre thread (principal ou du scheduler) cela fait un noeud.

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.


et pourquoi cela ??
j'ai indiqué:

void threadEntryPoint(void* refCon){
doIt(...);
endthread();
}

y'a des variables immédiates pas détruites avec ça ?? ("..." ne devait
pas être compris comme invoquant des constructeurs de temporaires)

si tu préfères:

void threadEntryPoint(void* refCon){
{
doItInBrackets(...);
}
endthread();
}

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 ?)


ben oui, simplement en sortant de "sa fonction main" par la porte normale.

Le problème reste les destructeurs des variables automatiques.
[...] S'il y a des variables automatiques,
en revanche, il faut faire gaffe.


je crois avoir précisément dit que le code devait être délimité /
périmétré (par fonction distincte ou accolades).

Sylvain.


Avatar
Sylvain
Serge Paccalin wrote on 15/11/2006 14:50:

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.


?!? la fin qui ne change rien et qui décrit ..., c'est le passage
"endthread automatically closes the thread handle..." ce n'est pas cela
que j'ai quoté.

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


shall ?

C'est inutile, donc. Et comme c'est dangereux...
c'est une erreur ("dangeureux" ??)



Non, pas « dangeureux », « dangereux ».


merci, ça c'est important!

Un risque de fuite mémoire (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.


oui, mes applis tournent régulièrement plusieurs mois, voire années,
sans reboot naturellement.

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 considère que tu as mal lu mon message, puisque je disais justement
de ne pas faire cela mais:

void ThreadBody(void *pUserData){
std::string Msg("Message d'erreur quelconque");
for (unsigned i = 0; i < 50000; ++i) ;
}

void __stdcall ThreadFunc(void *pUserData){
ThreadBody(pUserData);
_endthreadex(0);
}

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


ce point reste vrai, et ? tu veux supprimer toute les API qui pourraient
(éventuellement ou de manière certaine) avoir un risque lorsqu'elles
sont mal utilisées ??? je préfère éduquer les utilisateurs.

Sylvain.



Avatar
Serge Paccalin
Le 15.11.2006 23:50, :
Serge Paccalin wrote on 15/11/2006 14:50:
n'as-tu pas oublié la fin ?
La fin ne change rigoureusement rien. Elle décrit ce qui se passe da ns

endthread[ex], et il n'y a absolument aucune raison que le comportemen t
soit différent avec l'appel automatique ou avec un appel manuel.


?!? la fin qui ne change rien et qui décrit ..., c'est le passage
"endthread automatically closes the thread handle..." ce n'est pas cela
que j'ai quoté.


Non, la fin qui ne change rien, c'est : « Terminating a thread with a
call to endthread or _endthreadex helps to ensure proper recovery of
resources allocated for the thread. » Ça ne change rien parce que cet
appel a lieu de toutes façons, qu'il soit explicite dans ton code ou
pas, puisqu'il y a un appel à cette fonction après la sortie de la
fonction utilisateur. Donc : peu importe ce que fait _endthread[ex](),
ce sera fait quoi qu'il arrive.

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


shall ?


Ça fait biblique. Ou voyant extralucide (« tu l'appelleras, je le sai s »).

C'est inutile, donc. Et comme c'est dangereux...
c'est une erreur ("dangeureux" ??)

Non, pas « dangeureux », « dangereux ».



merci, ça c'est important!


Si tu n'es pas foutu de recopier correctement un mot que tu as sous les
yeux...

Un risque de fuite mémoire (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.


oui, mes applis tournent régulièrement plusieurs mois, voire anné es,
sans reboot naturellement.

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 considère que tu as mal lu mon message, puisque je disais justemen t
de ne pas faire cela mais:

void ThreadBody(void *pUserData){
std::string Msg("Message d'erreur quelconque");
for (unsigned i = 0; i < 50000; ++i) ;
}

void __stdcall ThreadFunc(void *pUserData){
ThreadBody(pUserData);
_endthreadex(0);
}


J'avais bien compris. Mais du code, ça bouge. Un jour ou l'autre, un
mainteneur rajoutera un objet dans ThreadFunc()...

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


ce point reste vrai, et ? tu veux supprimer toute les API qui pourraien t
(éventuellement ou de manière certaine) avoir un risque lorsqu'elle s
sont mal utilisées ???


Absolument. C'est pour ça que je fais du C++. Plus de gets(), de
scanf(), de sprintf(), de strcpy()...

je préfère éduquer les utilisateurs.


Jamais entendu parler de la loi de Murphy ? Si ça peut mal tourner, ç a
tournera mal un jour ou l'autre.

--
___________
_/ _ _`_`_`_) 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
James Kanze
Sylvain wrote:
James Kanze wrote on 15/11/2006 13:25:
Sylvain wrote:

n'as-tu pas oublié la fin ?


Est-ce que ça change quelque chose ?


est-ce que (chez MS) "helps to ensure proper recovery of resources"
change quelque chose ?!?


Mais vue qu'elle va être appelée de toute façon.

que veux-tu dire ? que le système est de toute façon en permanence
corrompu ?


Non, simplement qu'elle va être appelée de toute façon.

Si j'ai bien compris,
c'est un peu comme exit(), mais pour un thread.


oui.


Donc, un retour de la fonction par laquelle on a lancé le thread
l'appelle.

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.


certes, mais où est le retour de la fonction principale du
thread?? dans le scheduler du noyo ? (fote volontaire)


Selon la documentation citée, c'est le rétour de la fonction
dont on a passé l'adresse à _beginthread ou _beginthreadex. En
retournant de cette fonction, _endthread ou _endthreadex serait
appelée automatiquement.

ton point revient donc à considérer que l'on a le contrôle sur le
"lanceur de processus";


Mon point revient à considérer qu'on peut faire confiance à la
documentation, et quand elle dit que la fonction est appelée
automatiquement, elle est appelée automatiquement.

c'était le cas il y a de très nombreuses années avec des
threads tout-à-la-main sous MacOS (notamment), ce n'est pas le
cas avec ses API hydribes, ni avec le 100% MS.

or endthread doit être appeler par le thread se terminant, par lui-mê me,
pas un autre thread (principal ou du scheduler) cela fait un noeud.


D'après la documentation citée : « endthread or _endthreadex
is called automatically when the thread returns from the routine
passed as a parameter to _beginthread or _beginthreadex. »

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.


et pourquoi cela ??
j'ai indiqué:

void threadEntryPoint(void* refCon){
doIt(...);
endthread();
}

y'a des variables immédiates pas détruites avec ça ??


Pas dans ce cas précis. Ce qui n'invalide pas ce que j'ai dit :
les destructeurs des variables automatiques ne sont pas appelés.

D'après mon expérience, il arrive qu'on ajoute des variables
locales lors des évolutions. L'appel de endthread() ici est donc
fragile, puisque si on ajoute une variable locale qui a un
destructeur, ce destructeur ne sera pas appelé.

C'est exactement le même cas que exit() pour le processus. Si tu
veux un arrêt propre du processus, il faut que exit() soit
appelé. Mais il l'est implicitement, au retour de main, et en
fait, des appels explicits d'exit() sont fortement découragés en
C++, parce qu'ils empèchent l'appel des destructeurs.

("..." ne devait
pas être compris comme invoquant des constructeurs de temporaires)

si tu préfères:

void threadEntryPoint(void* refCon){
{
doItInBrackets(...);
}
endthread();
}


C'est mieux, mais c'est curieux comme idiome. Et il a exactement
le même comportement que :

void threadEntryPoint( void* refCon )
{
doIt( ... ) ;
}

(En fait, au moins si _beginthread functionne à peu près comme
pthread_create, le code serait forcement en accolades, parce
qu'il faudrait le mettre dans un bloc de try :

void threadEntryPoint( void* refCon )
{
try {
doIt( ... ) ;
} catch ( ... ) {
// Loggue exception inattendue...
}
}

Mais c'est une complication en plus, nécessaire pour écrire du
code robuste, mais à aborder une fois qu'on a déjà compris les
bases.)

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 ?)


ben oui, simplement en sortant de "sa fonction main" par la
porte normale.


Ce qui revient au même. Je comparais au processus et main, où il
existe aussi des possibilités comme abort(). Quand on appelle
abort(), on ne nettoie pas dans le processus, et ces ressources
non nettoyées par le systèmes (fichiers temporaires, etc.)
fuient. Dans le cas d'un processus, la plupart des ressources
sont nettoyées par le système, et on peut trouver les autres, et
les nettoyer à la main. Dans le cas d'un thread, en revanche,
pratiquement rien n'est nettoyé par le système, et il faut
absolument compter sur les destructeurs et les blocs de catch
pour le faire. Donc, l'appel direct de _endthread serait encore
plus nocif que l'appel d'exit().

Le problème reste les destructeurs des variables automatiques.
[...] S'il y a des variables automatiques,
en revanche, il faut faire gaffe.


je crois avoir précisément dit que le code devait être
délimité / périmétré (par fonction distincte ou accolades).


J'ai du le rater.

Si tu l'encapsule le démarrage du thread, comme tu l'as fait
dans les exemples, alors, c'est simplement un idiome comme un
autre. Aucun problème, sauf que je n'en vois pas la nécessité.

--
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
Serge Paccalin wrote:

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


shall ?


Ça fait biblique. Ou voyant extralucide (« tu l'appelleras, je le sai s »).


Juste une note sur la vocabulaire : ISO a une norme sur le
langage qui sert dans les normes. Dans une norme ISO (et aussi
dans les RFC, qui ont adopté le même vocabulaire), « shall »
(et aussi « must », au moins dans les RFC) signifie une
obligation absolue : « the program shall... » signifie que le
programme est illégal s'il ne le fait pas. (Comportement
indéfini, en C++, au moins que l'erreur exige une diagnostique.)
« Shall not », c'est une interdiction du même ordre.

Quand il s'agit plutôt des conseils (« recommendations »), le
mot employé est « should » (ou « may », mais « may not »
n'est pas utilisé).

Ça, c'est pour les normes (la bible dont réfère Serge ?). Je
n'ôserai pas dire que les mêmes règles s'appliquent à la
documentation Microsoft.

C'est inutile, donc. Et comme c'est dangereux...
c'est une erreur ("dangeureux" ??)

Non, pas « dangeureux », « dangereux ».



merci, ça c'est important!


Si tu n'es pas foutu de recopier correctement un mot que tu as
sous les yeux...


Sorry, Serge... Je ne connais personne qui ne fait jamais de
faute de frappe. S'il faisait systèmatiquement la même erreur,
on pourrait lui le signaler, poliment, et de préférence par
email, mais quand il s'agit d'un cas isolé, je crois qu'il faut
supposer une faute de frappe, et passer outre. Ça n'impacte
certainement pas ce qu'il essaie de dire.

--
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

C'est inutile, donc. Et comme c'est dangereux...
c'est une erreur ("dangeureux" ??)

Non, pas « dangeureux », « dangereux ».



merci, ça c'est important!


Si tu n'es pas foutu de recopier correctement un mot que tu as
sous les yeux...


Sorry, Serge... Je ne connais personne qui ne fait jamais de
faute de frappe. S'il faisait systèmatiquement la même erreur,
on pourrait lui le signaler, poliment, et de préférence par
email, mais quand il s'agit d'un cas isolé, je crois qu'il faut
supposer une faute de frappe, et passer outre. Ça n'impacte
certainement pas ce qu'il essaie de dire.


Sans doute, mais là, il reprenait un terme que j'avais employé, et le
mettait entre guillemets. Cela donnait l'impression qu'il me citait et,
d'une certaine façon, m'attribuait la paternité de cette faute.

--
___________
_/ _ _`_`_`_) 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
Sylvain
Serge Paccalin wrote on 16/11/2006 09:11:

Non, la fin qui ne change rien, c'est : « Terminating a thread with a
call to endthread or _endthreadex helps to ensure proper recovery of
resources allocated for the thread. » Ça ne change rien parce que cet
appel a lieu de toutes façons ...


mais, sauf à l'appeler, on ne sait pas quand!
ce détail ne te paraîtra sûrement pas pertinent, aussi je ne
t'expliquerais pas pourquoi cela pour être crucial.

garde la vision , beginthread lance immédiatement, au cycle d'horloge
suivant, le thread et celui-ci a entièrement complètement disparu dès la
sortie de son main.

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



Ça fait biblique. Ou voyant extralucide (« tu l'appelleras, je le sais »).


non, ça fait RFC 2119, citée dans tout RFP ou spécification
fonctionnelle (lire "cahier des charges") digne de ce nom; peut être ne
travailles-tu pas avec de tels documents.

C'est inutile, donc. Et comme c'est dangereux...
c'est une erreur ("dangeureux" ??)

Non, pas « dangeureux », « dangereux ».

merci, ça c'est important!



Si tu n'es pas foutu de recopier correctement un mot que tu as sous les
yeux...


sans t'avoir sous les yeux, je suis par contre sacrément toufu de me
rendre compte que je perds mon temps avec un mec n'apportant rien à ce
qui est discuté, épiloguant connement sur une coquille, et se prenant
pour un sur-dieu ("moi je code propre, les autres font de la merde, la
preuve même Murphy l'a dit").

donc tchao.

Sylvain.





Avatar
Serge Paccalin
Le 16.11.2006 22:52, :
Serge Paccalin wrote on 16/11/2006 09:11:
Non, la fin qui ne change rien, c'est : « Terminating a thread with a
call to endthread or _endthreadex helps to ensure proper recovery of
resources allocated for the thread. » Ça ne change rien parce que cet
appel a lieu de toutes façons ...


mais, sauf à l'appeler, on ne sait pas quand!
ce détail ne te paraîtra sûrement pas pertinent, aussi je ne
t'expliquerais pas pourquoi cela pour être crucial.


Elle est appelée de toutes façons dans le contexte du thread, c'est
évident, puisqu'elle ne reçoit aucun paramètre permettant de
l'identifier de l'extérieur.

garde la vision , beginthread lance immédiatement, au cycle d'horloge
suivant, le thread et celui-ci a entièrement complètement disparu d ès la
sortie de son main.


D'accord là-dessus. Mais son main, ce n'est pas la fonction utilisateur .
Il y a un peu de code avant pour tout mettre en place, et un peu de code
après pour nettoyer, lequel appelle endthread[ex].

À chaque fois, c'est « You can call » ; si cela devait provoqu er une
fuite de ressources système de l'oublier, ce serait « You must c all »,
ou, au minimum, « You should call »
shall ?

Ça fait biblique. Ou voyant extralucide (« tu l'appelleras, je le sais »).



non, ça fait RFC 2119, citée dans tout RFP ou spécification
fonctionnelle (lire "cahier des charges") digne de ce nom; peut être ne
travailles-tu pas avec de tels documents.


Si, bien sûr. Et la RFC 2119 n'introduit « shall » que comme un syn onyme
de « must », que j'avais employé moi-même. Et comme Microsoft ne
l'emploie pas du tout, il est faux de prétendre que Microsoft recommand e
d'appeler la fonction.

C'est inutile, donc. Et comme c'est dangereux...
c'est une erreur ("dangeureux" ??)

Non, pas « dangeureux », « dangereux ».

merci, ça c'est important!

Si tu n'es pas foutu de recopier correctement un mot que tu as sous le s

yeux...


sans t'avoir sous les yeux, je suis par contre sacrément toufu de me
rendre compte que je perds mon temps avec un mec n'apportant rien à c e
qui est discuté, épiloguant connement sur une coquille, et se prena nt
pour un sur-dieu ("moi je code propre, les autres font de la merde, la
preuve même Murphy l'a dit").


Je ne me prends pas pour un sur-dieu, loin de là, autrement je passerai s
mon temps à répondre sur tous les problèmes posés, et ce n'est p as
franchement *mon* profil.

--
___________
_/ _ _`_`_`_) 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
James Kanze
Sylvain wrote:
Serge Paccalin wrote on 16/11/2006 09:11:

Non, la fin qui ne change rien, c'est : « Terminating a thread with a
call to endthread or _endthreadex helps to ensure proper recovery of
resources allocated for the thread. » Ça ne change rien parce que c et
appel a lieu de toutes façons ...


mais, sauf à l'appeler, on ne sait pas quand!


Au rétour de la fonction, d'après ce qui est écrit. J'avoue que
ce n'est pas aussi clair que ce qui concerne exit() dans les
normes C/C++, mais j'interprète le texte cité à signifier que
l'appel aura lieu dès qu'on retourne de la fonction, comme si le
code appelant était quelque chose du genre :

_endthread( (*userFnc)(...) ) ;

ce détail ne te paraîtra sûrement pas pertinent, aussi je ne
t'expliquerais pas pourquoi cela pour être crucial.

garde la vision , beginthread lance immédiatement, au cycle d'horloge
suivant,


Ça m'étonnerait. Au moins sous Posix (mais je crois que Windows,
c'est pareil), il n'est pas défini quand le nouveau thread
démarre réelement. (Mais peut-être il y a malentendu sur le mot
« lancer ». Le nouveau thread existe dès l'appel à
beginthread, et peut être schéduler. Ce qui n'est pas défini,
évidemment, c'est si le schéduleur le choisit lui, ou l'ancien
thread, pour continuer l'exécution.)

le thread et celui-ci a entièrement complètement disparu dès la
sortie de son main.


Non plus. La contexte du thread doit durer au moins jusqu'au
join.

En fait, le thread commence et termine dans du code système (ou
bibliothèque) ; c'est ce code qui appelle ta fonction. Et qui
appelle _endthread, si tu ne l'as pas fait.

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



Ça fait biblique. Ou voyant extralucide (« tu l'appelleras,
je le sais »).


non, ça fait RFC 2119, citée dans tout RFP ou spécification
fonctionnelle (lire "cahier des charges") digne de ce nom; peut être ne
travailles-tu pas avec de tels documents.


Ça fait aussi ISO (ISO 2382, je crois) ; c'est le langage des
normes.

Ça correspond aussi très fort à l'utilisation dans la traduction
dite du roi Jacques de la Bible : chacun des dix commandements
commence « Thou shalt not... », par exemple. C'est assez
subtile, mais quand un anglophone entend quelque chose du genre
« x shall » ou « x shall not », il pense effectivement aux
injonctions bibliques (de l'ancien testament, en tout cas).
(Mais ce n'est pas la seule utilisation possible, ni même la
plus courante, et beaucoup dépend du contexte.)

En l'occurance, je ne sais pas si Serge faisait référence ici à
la bible du groupe (c-à-d ISO 14882), ou à la Bible tout court.

Je ne sais pas si les auteurs de la doc Microsoft ont été aussi
rigueureux dans leur utilisation du langage. Néaumoins, si je
régarde l'anglais original, « You can [...]; however[...] »
suggère très fortement que l'appel est facultatif ; que c'est
une façon de terminer le thread sans retourner de la fonction
principale du thread. C'est mon interprétation du passage cité,
mais je ne crois pas que le passage soit très ambigu ; je crois
que prèsque n'importe quel anglophone l'interpreterait de cette
façon.

Note bien que le but de ISO 2382 et de RFC 2119, c'est bien de
mettre les points sur les i, pourqu'on ne dépend pas des
sensitivités linguistiques d'un anglophone. Ils ne font que
codifier une certaine utilisation naturelle du langage, et ne
serait pas nécessaire si les normes ne devaient être lu que des
anglophones de naissance.

Toutefois : je crois que tu as expliqué ta position clairement,
et que c'est clair que tu prends bien en compte le problème des
destructeurs. Ensuite, c'est une question de convention, et la
tienne est aussi valable qu'une autre.

--
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
Sylvain
James Kanze wrote on 17/11/2006 10:01:

mais, sauf à l'appeler, on ne sait pas quand!


Au rétour de la fonction, d'après ce qui est écrit.


"au retour" n'est nullement garanti (pas par l'annoncé en tout cas).

J'avoue que
ce n'est pas aussi clair que ce qui concerne exit() dans les
normes C/C++, mais j'interprète le texte cité à signifier que
l'appel aura lieu dès qu'on retourne de la fonction, comme si le
code appelant était quelque chose du genre :

_endthread( (*userFnc)(...) ) ;


ou qlq chose comme:

dans pool des threads actifs:
for(;;){
sleep
yield
}
pour chaque thread
initContext
userCallback
moveToDeadThreadZone

dans pool des threads en cours de terminaison:
endthread (quand-j'ai-le-temps)

sans implémentation concrête d'un gestionnaire de processus, tout n'est
qu'hypothèse; sans spécification de leur fonctionnement (et évidemment
chaque OS fait comme il souhaite) aucune garantie n'existe sur ce point.

ce détail ne te paraîtra sûrement pas pertinent, aussi je ne
t'expliquerais pas pourquoi cela pour être crucial.

garde la vision , beginthread lance immédiatement, au cycle d'horloge
suivant,


Ça m'étonnerait. Au moins sous Posix (mais je crois que Windows,
c'est pareil), il n'est pas défini quand le nouveau thread
démarre réelement. (Mais peut-être il y a malentendu sur le mot
« lancer ». Le nouveau thread existe dès l'appel à
beginthread, et peut être schéduler. Ce qui n'est pas défini,
évidemment, c'est si le schéduleur le choisit lui, ou l'ancien
thread, pour continuer l'exécution.)


bien sur, dois-je préciser que "la vision" était une caricature.

le thread et celui-ci a entièrement complètement disparu dès la
sortie de son main.


Non plus. La contexte du thread doit durer au moins jusqu'au
join.


bien sur aussi.

En fait, le thread commence et termine dans du code système (ou
bibliothèque) ; c'est ce code qui appelle ta fonction. Et qui
appelle _endthread, si tu ne l'as pas fait.


"ce code" est une hypothèse; cela peut être "ces codes" avec des
priorités différentes, une comparaison simple pour illustrer est un GC.

Je ne sais pas si les auteurs de la doc Microsoft ont été aussi
rigueureux dans leur utilisation du langage. Néaumoins, si je
régarde l'anglais original, « You can [...]; however[...] »
suggère très fortement que l'appel est facultatif ; que c'est
une façon de terminer le thread sans retourner de la fonction
principale du thread. C'est mon interprétation du passage cité,
mais je ne crois pas que le passage soit très ambigu ; je crois
que prèsque n'importe quel anglophone l'interpreterait de cette
façon.


je l'interprète également comme cela; mais cela ne change rien.
l'appel est bien sur facultatif, cela inclut que l'on peut choisir de le
faire - crier au loup (à l'API de Satan) parce quelqu'un pourrait
masquer un destructeur avec est ?... hmm, contre-informatif.

Sylvain.


1 2 3