Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1517 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  classes et threads

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

classes et threads

n°243348
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 10:43:08  profilanswer
 

bonjour, je voudrais créer une classe, avec une routine en tache de fond dedans. je m'explique par un exemple :
 
class MyClass {
 public:
  MyClass(void) {/*Création d'un thread p-e ac CreateThread*/};
  ~MyClass(void) {/*destruction du thread*/};
 private:
  DWORD WINAPI ThreadEntry(LPVOID lpParameter){/*Entrée du thread*/return 0;}
}
 
mais voila, ne fonction 'WINAPI' ne fonctionne pas comme membre de classe, et puis je ne sais pas comment terminer proprement le thread lorsque la classe est détruite.
 
merci de votre aide


---------------
-( BlackGoddess )-
mood
Publicité
Posté le 12-11-2002 à 10:43:08  profilanswer
 

n°243364
botman
Cubeur
Posté le 12-11-2002 à 11:11:01  profilanswer
 

moi j'utilise les fonctions de la librairie pthread ....
 
dans ma classe toto j'ai un membre de type pthread_t , lors de l'appel du constructeur de la calsse j'appelle la fonction pthread_create ou pthread_init (j'sais plus) pour creer/initialiser mon thread ...
mon destructeur de classe, lui, je le surcharge et j'appelle pthread_destroy sur le thread ...


---------------
"OCPLB : On Casse Pas Le Binôme, 'moiselle Jade, Carlson & Peters, page 823 !"
n°243372
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 11:17:57  profilanswer
 

euh ... oui ... je connais pas la lib pthread ... je peux la trouver ou ? parce que la je suis pas vraiment avancé


---------------
-( BlackGoddess )-
n°243377
YungMakko
Posté le 12-11-2002 à 11:24:56  profilanswer
 

Tu es sous quel environment? (OS, Outil de development etc)


---------------
In tartiflette, we trust!
n°243380
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 11:29:53  profilanswer
 

@rf oui pardon
je suis sous windows (je cherche une solution qui fonctionne pour 95/98/me/nt4/2000/xp (enfin sous win32 quoi)), et je dev avec vc++ 6


---------------
-( BlackGoddess )-
n°243383
YungMakko
Posté le 12-11-2002 à 11:38:00  profilanswer
 

BlackGoddess a écrit a écrit :

@rf oui pardon
je suis sous windows (je cherche une solution qui fonctionne pour 95/98/me/nt4/2000/xp (enfin sous win32 quoi)), et je dev avec vc++ 6




 
Tu es allérgique aux MFC ? (je te comprends), parce que sinon tu as tout ce qu'il faut avec les MFC pour créer très facilement des threads ( 2 solutions possible ).
Sinon tu as l'API Windows: CreateThread, auquel tu passes la fonction qui doit être executée dans le thread créé (voir MSDN pour les paramètres exactes). Cette fonction marche sur toutes les plateforms de Win9x , Me, NT 3.51, NT4, 2000, XP ...


---------------
In tartiflette, we trust!
n°243394
gatorette
Posté le 12-11-2002 à 11:50:21  profilanswer
 

Une fonction "Thread" ne peut être déclarée comme membre d'une classe (comme tu as pu le constater). Cela est dû à la façon dont sont générées les fonctions membres en C++.
La seule solution qui existe est de la déclarer en static. Cependant il faut savoir que la fonction n'est alors pas reliée à une instance de la classe (pas de this par exemple). Il te faut donc envoyer le this en tant que paramètre. De même lors de la création de la thread, indique bien MyClass::ThreadEntry.
En fait cette solution ne présente que peu de différences avec l'utilisation d'une fonction globale. Elle peut être utile pour des raisons de clarté.


---------------
each day I don't die is cheating
n°243395
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 11:50:37  profilanswer
 

je suis en effet allergique aux MFC ... pour CreateThread, ce qui me bloque c l'erreur du compilo : un membre de classe ne peut pas être WINAPI alors que le paramètre de CreateThread pour le point d'entrée du thread l'oblige. Et aussi, je cherche comment terminer proprement mon thread a la destruction de la classe


---------------
-( BlackGoddess )-
n°243400
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 11:52:23  profilanswer
 

par exemple un TerminateThread serait tres sale, mais je n'ai pas d'autres idées ...


---------------
-( BlackGoddess )-
n°243403
YungMakko
Posté le 12-11-2002 à 11:55:03  profilanswer
 

Voir la reponse de "gatorette", c'est effet la solution.


---------------
In tartiflette, we trust!
mood
Publicité
Posté le 12-11-2002 à 11:55:03  profilanswer
 

n°243406
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 11:56:04  profilanswer
 

ah oups oui dsl j'avais pas vu, il a posté pendant que j'ecrivais.


---------------
-( BlackGoddess )-
n°243409
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 12:00:00  profilanswer
 

si on passe en paramètre this, le ThreadEntry pourra-t-il accéder aux memebres privés de l'objet ?


---------------
-( BlackGoddess )-
n°243410
YungMakko
Posté le 12-11-2002 à 12:10:55  profilanswer
 

BlackGoddess a écrit a écrit :

si on passe en paramètre this, le ThreadEntry pourra-t-il accéder aux memebres privés de l'objet ?




 
Non impossible; tu ne peux pas accéder à des membres non statique d'un object dans une fonction statique; si tu réfléchis, le compilateur ne peu savoir à l'avance l'adresse de ton object (tu peux créér des centaines d'instance de ton object en même temps, hors, il n'existe qu'une seule implementation de ta fonction statique!!! )
 
Par contre, depuis ta classe, quand tu apelles le thread, tu peux par exemple créér en dynamique une petite structure que tu remplis avec les données de la classe necessaire au thread, et passer l'adresse de cette structure à la fonction CreateThread.


---------------
In tartiflette, we trust!
n°243412
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 12:17:39  profilanswer
 

ah !!! oui super ca je n'y avais pas pensé !
bin ca resoud aussi le pb de la destruction : ds le destructeur je peux mettre qqchose ds la structure (par exemple MustExit = TRUE) pour que comme ca la fonction du thread sache qu'il faut qu'elle arrete de travailler
 
merci bcp @ vous


---------------
-( BlackGoddess )-
n°243414
YungMakko
Posté le 12-11-2002 à 12:25:56  profilanswer
 

You welcome!  :sol:


---------------
In tartiflette, we trust!
n°243417
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 12:28:59  profilanswer
 

ah oui, encore une question : vu que c'est la mm fonction qui est appelé a chaque fois, si on instancie 2 fois la classe, cela va créer 2 threads, or c'est 2 fois la mm fonction qui va etre appelé pour les threads. il ne risque pas d'y avoir de l'ecrasement de données ? je m'explique par un exemple :
 
DWORD EntryPoint(LPVOID lpParameter)
{
  DWORD dwTC = GetTickCount();
}
 
mettons par exemple qu'à la 1ere instanciation, la valeur récupérée ds dwTC soit 1000, puis on instancie une 2eme fois la classe, dwTC pour la 2eme instance sera par exemple de 3000. La question est : le 1000 de la 1ere instanciation va-t-il devenir un 3000 ?
 
si telle est le cas, je peux p-e me débrouiller avec des références :
 
DWORD EntryPoint(LPVOID lpParameter)
{
  DWORD* pdwTC = new DWORD;
  (*pdwTC) = GetTickCount();
}
 
ds ce cas, cela fonctionnera-t-il ?


---------------
-( BlackGoddess )-
n°243418
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 12:32:30  profilanswer
 

j'ai oublié le static DWORD WINAPI MyClass::EntryPoint(LPVOID lpParameter)
à la place de DWORD EntryPoint(LPVOID lpParameter)
ne faites également pas attention à l'oubli de return 0; a la fin
c t juste pour l'exemple.


---------------
-( BlackGoddess )-
n°243422
YungMakko
Posté le 12-11-2002 à 12:37:50  profilanswer
 

Il n'y a pas de problème à ce que la fonction soit appellée plusieurs fois; les problème arrivent seulement quand plusieurs thread accèdent à un même object; dans ce cas, il faut que tu utilises des system de synchronisation ( mutex, critical section ).


---------------
In tartiflette, we trust!
n°243423
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 12:42:11  profilanswer
 

ok, d'accord :)
 
justement, j'avais entendu parler de critical section, je me demandais a quoi ca servait. tu connaitrais par hasard des liens pour savoir comment s'en servir ?
 
sinon les mutex, j'en ai juste entendu parler comme moyen pour pas qu'on puisse lancer 2 fois l'app : elle crée un mutex au démarrage qd elle se lance, et si ca retourne AlreadyExist, alors c pas la 1ere instance de l'app. (c un peu restrinct par rapport à l'utilisté des mutex je suppose :p)


---------------
-( BlackGoddess )-
n°243428
YungMakko
Posté le 12-11-2002 à 12:48:21  profilanswer
 

Voir:  
 
* InitializeCriticalSection() dans MSDN et fonctions associées, c'est une fonction du SDK Win32.  
 
* Voir le topic "Synchronisation overview" toujours dans MSDN
 
* Sinon: www.codeguru.com  il y a plein d'exemple, il suffit de chercher un peu
 
* www.thecodeproject.com, idem, plein d'exmples.
 
Avec ça, si tu t'en sors pas!  :D  
 


---------------
In tartiflette, we trust!
n°243432
SoWhatIn22
Posté le 12-11-2002 à 12:56:59  profilanswer
 

YungMakko a écrit a écrit :

 
 
Non impossible; tu ne peux pas accéder à des membres non statique d'un object dans une fonction statique; si tu réfléchis, le compilateur ne peu savoir à l'avance l'adresse de ton object (tu peux créér des centaines d'instance de ton object en même temps, hors, il n'existe qu'une seule implementation de ta fonction statique!!! )
 
Par contre, depuis ta classe, quand tu apelles le thread, tu peux par exemple créér en dynamique une petite structure que tu remplis avec les données de la classe necessaire au thread, et passer l'adresse de cette structure à la fonction CreateThread.




 
Il me semble qu'en déclarant la fonction statique friend de la classe, alors cette fonction statique peut, en utilsant un pointeur sur l'instance, accéder à ses variables privées.
 
De plus, la structure en argument qui contient les données, outre le fait que ce n'est pas très pratique, interdit la consultation utlérieure des attributs de le l'instance ainsi que leur modification. Donc si une variable membre change, le thread ne pourra pas le savoir, de même qu'il ne pourra pas mettre à jour des attrubuts de cette instance (sauf bien sur si la classe dispose de méthodes pour cela, mais à ce moment là autant laisser les attributs en public...).

n°243436
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 13:04:08  profilanswer
 

SoWhatIn22 : si j'ai bien compris, si je déclare ma fonction en static friend DWORD WINAPI MyClass::ThreadEntry(LPVOID lpParameter) alors en passant comme argument this, je pourrais alors avoir acces aux membres privés en faisant : ((MyClass*)lpParamter)->MembrePrivé ? ai-je bien compris ?


---------------
-( BlackGoddess )-
n°243437
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 13:06:10  profilanswer
 

pour la structure de données, si le thread recoit un pointeur vers cette structure il ne pourra pas changer les données de cette structure ???????


---------------
-( BlackGoddess )-
n°243445
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 13:26:26  profilanswer
 

c bon g compris les critical sections avec les msdn, merci yungmakko  :)


---------------
-( BlackGoddess )-
n°243485
YungMakko
Posté le 12-11-2002 à 14:13:30  profilanswer
 

SoWhatIn22 a écrit a écrit :

 
 
Il me semble qu'en déclarant la fonction statique friend de la classe, alors cette fonction statique peut, en utilsant un pointeur sur l'instance, accéder à ses variables privées.
 
De plus, la structure en argument qui contient les données, outre le fait que ce n'est pas très pratique, interdit la consultation utlérieure des attributs de le l'instance ainsi que leur modification. Donc si une variable membre change, le thread ne pourra pas le savoir, de même qu'il ne pourra pas mettre à jour des attrubuts de cette instance (sauf bien sur si la classe dispose de méthodes pour cela, mais à ce moment là autant laisser les attributs en public...).
 




 
Oui, en declarant la fonction statique de classe, ça fonctionne, le problème c'est que tous les membres de la classe doivent être statique s'y tu veux y acceder depuis la fonction statique! Ce qui n'est pas non plus vraiment pratique!!! (interet d'avoir une classe?)


Message édité par YungMakko le 12-11-2002 à 14:14:03

---------------
In tartiflette, we trust!
n°243487
YungMakko
Posté le 12-11-2002 à 14:14:38  profilanswer
 

BlackGoddess a écrit a écrit :

pour la structure de données, si le thread recoit un pointeur vers cette structure il ne pourra pas changer les données de cette structure ???????




 
Si sans problème; donc faire attention justement à cela!


---------------
In tartiflette, we trust!
n°243496
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 14:28:05  profilanswer
 

c justement la ou on peut mettre une critical section si g bien compris l'utilité du truc ? pour pas ke le thread veuille lire qqchose de la structre pendant que l'objet l'ecrit, ce genre de chose, c ca ?


---------------
-( BlackGoddess )-
n°243522
YungMakko
Posté le 12-11-2002 à 15:08:46  profilanswer
 

BlackGoddess a écrit a écrit :

c justement la ou on peut mettre une critical section si g bien compris l'utilité du truc ? pour pas ke le thread veuille lire qqchose de la structure pendant que l'objet l'ecrit, ce genre de chose, c ca ?




 
Voila c'est ça, dans ton thread par exemple, quand tu accedes à une structure pour la lire ou la modifier:
 
...
Locker la criticale section
 
Lire/Modifier la structure (se debrouiller pour passer le minimum de temps ici pour ne pas trop bloquer les autres threads qui voudraient acceder aussi aux données; il peut être judicieux de stocker dans des variable locales les données necessaires, si les traitements sont long, et delocker immediatement la criticale section).
 
Delocker la criticale section
...


---------------
In tartiflette, we trust!
n°243565
blackgodde​ss
vive le troll !
Posté le 12-11-2002 à 16:13:03  profilanswer
 

super, merci, g appris plein de truc du ++ du c, et aussi ca faisait lgtps que les critical section me tapaient sur le système, merci bcp :)


---------------
-( BlackGoddess )-
n°243602
SoWhatIn22
Posté le 12-11-2002 à 16:53:47  profilanswer
 

YungMakko a écrit a écrit :

 
 
Oui, en declarant la fonction statique de classe, ça fonctionne, le problème c'est que tous les membres de la classe doivent être statique s'y tu veux y acceder depuis la fonction statique! Ce qui n'est pas non plus vraiment pratique!!! (interet d'avoir une classe?)




 
non. Si l'instance qui démarre le thread donne à ce thread un pointeur sur cette instance, il n'y a aucun soucis...
 
int MA_CLASSE::StartThread()
{
   // on crée le thread
   CreateThread( ..., start_routine, (void *)this, ... );
 
   /// bla bla bla...
   return 0;
}
 
/// fonction du thread
int start_routine( void * optarg )
{
   /// on récupère un pointeur sur l'instance
   MA_CLASSE * mon_instance;
   mon_instance = (MA_CLASSE *)optarg;
 
   /// et on fait ce que l'on veut avec l'instance
   mon_instance->min_attribut_prive0 = 7;
 
   /// etc...
 
   return 0;
}
 
 
 
 
je ne vois pas où est le problème la dedans... Une fonction statique ne peut manipuler que des attributs statiques de sa classe. Mais si on dispose d'un pointeur sur l'instance que l'on veut manipuler, alors on peut bien faire ce que l'on veut sur cette instance.
 
a+

n°243611
YungMakko
Posté le 12-11-2002 à 17:01:07  profilanswer
 


 
je ne vois pas où est le problème la dedans... Une fonction statique ne peut manipuler que des attributs statiques de sa classe. Mais si on dispose d'un pointeur sur l'instance que l'on veut manipuler, alors on peut bien faire ce que l'on veut sur cette instance.
 
a+
[/citation]
 
Dans le cas que tu as ecris en effet; mais si la fonction du thread est membre de la classe (quoi que je n'ai jamais essayé avec un Worker Thread, je bosse souvent avec des User Interface Thread), il est impossible d'accéder au membre non statique de classe depuis la fonction statique membre de cette même classe (ce qui est logique!) Le compilo te sors une erreur d'accès...


---------------
In tartiflette, we trust!
n°243878
Musaran
Cerveaulté
Posté le 13-11-2002 à 03:58:27  profilanswer
 

Rhaa !
 
A part le nom imbriqué, une fonction statique de classe est une fonction oridinaire.
Si on lui transmet un pointeur sur un objet de cette classe, elle peut accéder à tous ses membres vu qu'elle fait partie de la classe.
Et si elle n'en fait pas partie, il suffit de la déclarer friend.

Code :
  1. class MyClass{
  2. static DWORD WINAPI MyClass::ThreadEntry(LPVOID);
  3. int MembrePrive;
  4. public:
  5. MyClass(){
  6.  ThreadEntry((LPVOID)this); //le cast n'est pas (void*) !
  7. }
  8. }
  9. static DWORD WINAPI MyClass::ThreadEntry(LPVOID lpParameter){
  10. MyClass* creator= (MyClass*)lpParamter; //constance éventuelle ignorée
  11. creator->MembrePrive; //accès ok
  12. MembrePrive; //pas bon, le this implicite n'existe pas
  13. }

C'est pas testé, mais je ne vois pas de raison que ça ne marche pas.
A moins que WINAPI exige un nommage C, incompatible avec l'imbrication de nom.
 
Attention, on perd l'information de constance du créateur !


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°243890
blackgodde​ss
vive le troll !
Posté le 13-11-2002 à 08:29:52  profilanswer
 

nan mais déjà que c pas facile pour moi a comprendre, si en plus personne n'est d'accord ... :p
 
ca veut dire quoi :
"Attention, on perd l'information de constance du créateur !"
 
et aussi je comprends pas :  
//le cast n'est pas (void*) !
pour (LPVOID)this


---------------
-( BlackGoddess )-
n°243895
YungMakko
Posté le 13-11-2002 à 09:20:40  profilanswer
 

Oui en effet en passant comme ça, ça marche tout à fait!
C'est pour acceder directement au membre que ça ne marche pas (evidemment!)
 
 
Si si, tout le monde est d'accord!   :D


---------------
In tartiflette, we trust!
n°243900
blackgodde​ss
vive le troll !
Posté le 13-11-2002 à 09:43:56  profilanswer
 

ah bien tlm est d'accord :)
 
mais g tjs pas compris l'histoire du créateur constant et du cast void* ... si qq1 pouvait m'expliquer :)


---------------
-( BlackGoddess )-
n°244897
Musaran
Cerveaulté
Posté le 14-11-2002 à 03:04:05  profilanswer
 

Citation :

Attention, on perd l'information de constance du créateur !

Code :
  1. const MyClass mc;
  2. //...
  3. static DWORD WINAPI MyClass::ThreadEntry(LPVOID lpParameter){
  4. MyClass* creator= (MyClass*)lpParamter; //constance éventuelle ignorée
  5. creator->threadisrunning= true; //PAN ! T'es mort.

Ça suffit comme explication ?
Il n'y a pas de problème si threadisrunning est qualifié "mutable".
 

Citation :

le cast n'est pas (void*) !

La fonction ThreadEntry prend un LPVOID comme argument.

Code :
  1. ThreadEntry((LPVOID)this); //au lieu d'écrire ça...
  2. ThreadEntry((void* )this); //...certains écrivent ça.

"Certains" fainéants ou qui se croient malins vont avoir une surprise le jour du passage au 64 bits:
void* sera naturellement un pointeur 64 bits.
LPVOID restera à sa définition historique de 32 bits.
 
Voilà, c'est juste un excellent moyen de se tirer à retardement un obus dans le pied.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°244921
blackgodde​ss
vive le troll !
Posté le 14-11-2002 à 09:14:12  profilanswer
 

k, g compris l'histoire du void*, mais pour la constance du créateur, si g bien compris, c si on délcare de pointeur vers l'objet en constante, cela ne sera pas repercuté sur TreadEntry, c ca ?


---------------
-( BlackGoddess )-
n°245698
Musaran
Cerveaulté
Posté le 15-11-2002 à 03:00:51  profilanswer
 

Oui.
Le pointeur LPVOID oblige à utiliser une cast, et de ce fait ThreadEntry ignore si l'objet est constant ou pas.
C'est tout.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°245705
blackgodde​ss
vive le troll !
Posté le 15-11-2002 à 08:03:04  profilanswer
 

bin merci me voila fortement eclairé now :)
 
merci bcp @ tous :)


---------------
-( BlackGoddess )-
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  classes et threads

 

Sujets relatifs
petite question sur les classesObjets, Classes, Fonctions avec objets en paramétres, *, & :Prob.
connaissez pas des exercices résolus en vc++(relations /e classes)????Question simple sur les classes amies
C++ et threads + eCos[Threads/C] Fonction non bloquante checkant si un thread est fini...
Rational Rose : cacher des classes dans un diagramme...Organiser mes librairies de classes
[VC++ SANS MFC] exporter des classesC XLib Threads - comment envoyer un message ?
Plus de sujets relatifs à : classes et threads


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR