[C] Producteur/consommateur avec threads en C sur liste chainée...

Producteur/consommateur avec threads en C sur liste chainée... [C] - C - Programmation

Marsh Posté le 19-10-2003 à 13:06:02    

Hello :)
 
Ca fait un bail que j'ai pas bossé sur les mutex et compagnie, donc il me faudrait une peu d'aide sur quelque chose d'assez bidon.
 
Le schema de mon programme est un processus maitre qui est producteur et X threads qui sont consommateurs.
 
Le process maitre remplit une liste chainée, les threads la vident et traitent les demandes.
 
La ou je me pose des question, c'est dans le cas ou la liste est vide.
 
je m'explique : pour l'instant, pour qu'un thread puisse faire un pop d'un job sur la liste, il doit réussir a locker l'mutex.
 
Il ferme le mutex, prends son job, rouvre le mutex.
 
Seulement voilà, avec une archi pareille, les fils vont prendre en boucle les mutex meme si la liste est vide. En gros, il faudrait que, si la liste est vide, que le maître puisse la remplir a nouveau.
 
Etaussi, que le maitre aie priorité sur le remplissage de la liste face aux consommateurs.
 
Comment vous réaliseriez cela, pour avoir des performances optimales ?
 
merci :jap:

Reply

Marsh Posté le 19-10-2003 à 13:06:02   

Reply

Marsh Posté le 19-10-2003 à 13:14:07    

en fonction de la bibliothèque que tu utilises, tu doit pourvoir trouver quelque chose pour gérer les conditions, des attentes conditionnelles

Reply

Marsh Posté le 19-10-2003 à 13:53:12    

j'utilise pthread.d ... donc oui j'ai une condition ( pthread_cond_t et compagnie...)
 
Mais je mets quoi comme condition :??:
 
Et surtout, je voius moyennement comment ca marche... y a un exemple la, mais je vois pas pourquoi les autres doivent attendre ...
 
http://monge.univ-mlv.fr/~roussel/ [...] rs_ex.html

Reply

Marsh Posté le 19-10-2003 à 13:53:53    

Reply

Marsh Posté le 19-10-2003 à 14:03:38    

mmmmh...
 
Donc si je mets une condition "liste non vide", tout mon truc marche parfaitement... c'est bien ca ?  
 
Donc l'algo ca va etre ( si j'ai bien capté ).
 
Maitre :

Citation :

attends requete
requete arrivée, lock mutex de la liste
ajout requete liste
delock mutex
signal condition OK
goto debut


 
esclave

Citation :

prends mutex + condition
pop job de la liste  
delock mutex
goto debut


 
C'est bien ca ou j'ai faux ? J'ai du mal a saisir le concept, j'avoue :/

Reply

Marsh Posté le 19-10-2003 à 14:05:46    

nan ca doit pas etre ca :/
 
Rah j'arrive pas a capter le truc des conditions :/ Ca s'apelle condition mais ca amrche comme un signal ?

Reply

Marsh Posté le 19-10-2003 à 14:06:15    

voilà
 
un exemple 1 - 1 en C++
http://boost.org/libs/thread/example/condition.cpp

Reply

Marsh Posté le 19-10-2003 à 14:10:03    


 
Euh... c'est du chinois la :lol:
 
:sweat:  
 
Enfin je pense que j'ai mon idée... je vais reprendre l'exemple bcp + simple qui se trouve la : http://monge.univ-mlv.fr/~roussel/ [...] rs_ex.html
 
Et faire le même schéma de communication .
 
je pense qu'il s'applique a mon problème.


Message édité par Tetedeiench le 19-10-2003 à 14:10:25
Reply

Marsh Posté le 19-10-2003 à 14:15:05    

En fait, il faudrait que je fasse un truc de "priorité", dans le genre :
 
maître :
-attente requete
-lock mutex
-ajout requete dans liste
-condition remplie ( on vient d'en ajouter un...)
-delock mutex
 
esclave :
-essai lock mutex si condition remplie
-prendre requete
-si liste pas vide alors condition remplie
-delock mutex
-traitement requete
 
Dans ce cas la, je pense que cela marche, non ?  
 
Ton avis taz ?

Reply

Marsh Posté le 19-10-2003 à 14:41:14    

tout ça ne peut pas bien marcher puisqu'une condition doit etre associée à un mutex pour avoir le bon comportement

Reply

Marsh Posté le 19-10-2003 à 14:41:14   

Reply

Marsh Posté le 19-10-2003 à 14:43:44    

le moindre usage doit ressembler à ça
 

Code :
  1. pthread_mutex_lock(&resume_condition_mutex);
  2. pthread_cond_wait(&resume_condition, &resume_condition_mutex);
  3. pthread_mutex_unlock(&resume_condition_mutex);


 
et de l'autre coté (ici en broadcast
 

Code :
  1. pthread_mutex_lock(&resume_condition_mutex);
  2. pthread_cond_broadcast(&resume_condition);
  3. pthread_mutex_unlock(&resume_condition_mutex);

Reply

Marsh Posté le 19-10-2003 à 14:55:36    

Voilà ce que j'ai fait ( en version rapidos hein, ca fait 2 ans que j'ai pas fait de C )
 

Code :
  1. /****************************************************************************************/
  2. /***                                       ESCLAVES                                   ***/
  3. /****************************************************************************************/
  4. void* thfunc(void* id)
  5. {
  6.   httpjob* curjob;
  7.   printf("Thread %d\n",id);
  8.   while (1)
  9.     {
  10.       pthread_cond_wait(&jlist_cond,&jlist_mutex);
  11.       curjob = pophead();
  12.       pthread_mutex_unlock(&jlist_mutex);
  13.       printf("thread %d got job %d\n",id,curjob->num);
  14.       free(curjob);
  15.     }
  16. }
  17. /****************************************************************************************/
  18. /***                                   PROCESSUS MAITRE                               ***/
  19. /****************************************************************************************/
  20. int main(char* argv[],int argc)
  21. {
  22.   FILE* f;
  23.   int i,numjob;
  24.   httpjob* job;
  25.   pthread_t id;
  26.   //Initialisation variables globales. Le NULL sert a avoir les attributs par d?éfaut.
  27.   jlist.head = jlist.tail = NULL;
  28.   pthread_mutex_init(&jlist_mutex,NULL);
  29.   pthread_cond_init(&jlist_cond,NULL);
  30.   //  f = fopen("config.c","rw" );
  31.   for (i=0;i<5;i++)
  32.     pthread_create(&id,NULL,thfunc,(void*) i);
  33.   printf("Waiting for numbers\n" );
  34.   while (1)
  35.     {
  36.       scanf("%d\n",&numjob);
  37.       job = (httpjob*) malloc (sizeof(httpjob));
  38.       job->num = numjob;
  39.       job->next = NULL;
  40.       pthread_mutex_lock(&jlist_mutex);
  41.       printf("mutex locked\n" );
  42.       addjobinlist(job);
  43.       printf("job added\n" );
  44.       pthread_mutex_unlock(&jlist_mutex);
  45.       pthread_cond_signal(&jlist_cond);
  46.     }
  47.    
  48.    
  49.   return 1;
  50. }


 
Ca a l'air de bien marcher...
 
Enfin j suis sur que taz va me dire que la syntaxe est moche, désolé par avance :/


Message édité par Tetedeiench le 19-10-2003 à 14:56:11
Reply

Marsh Posté le 19-10-2003 à 15:01:43    

voir mon message précédent, lire les man
 
sinon tu peux tout initialisé statiquement, lis les man

Reply

Marsh Posté le 19-10-2003 à 15:06:05    

tetedeiench a écrit :

Voilà ce que j'ai fait ( en version rapidos hein, ca fait 2 ans que j'ai pas fait de C )


Tu ne fais plus que du VB?  :whistle:  
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 19-10-2003 à 15:09:04    

Taz a écrit :

voir mon message précédent, lire les man
 
sinon tu peux tout initialisé statiquement, lis les man


Ben, quelle est la différence avec ce que j'ai fait :??:
 
je vois pas :??:

Reply

Marsh Posté le 19-10-2003 à 15:13:30    

enchasse les opérations cond* dans le mutex associé, comme dit dans le man

Reply

Marsh Posté le 19-10-2003 à 15:20:03    

Taz a écrit :

enchasse les opérations cond* dans le mutex associé, comme dit dans le man


Voilà le souci : ca veut rien dire pour moi ca.
 
Détaille, je vois rien la dessus dans les différents mans ( tu penses que je les ai lus avant de poster :/ )

Reply

Marsh Posté le 19-10-2003 à 15:41:02    

D'ailleurs, d'après ce lien, j'ai utilisé ca pas si mal que ca, nan ?
 
http://monge.univ-mlv.fr/~roussel/ [...] linux.html
 
Evidemment y a le traitement qui jouera apres, mais bon... ca m'a l'air bon ?
 
je vois pas ce que tu veux dire taz :??:


Message édité par Tetedeiench le 19-10-2003 à 15:41:19
Reply

Marsh Posté le 19-10-2003 à 19:25:38    

lis le man, vois l'exemple. il faut enchasser tout ça, pthread_cond srentre dans el mutex si la condition est vérifiée.

Reply

Marsh Posté le 19-10-2003 à 19:35:34    

BELENG !
 
Vla que je tilte ce que tu voulais dire par "enchâsser".
 
mais dans mon cas, faut pas que j'enchasse !
 
Le signal est la pour leur dire qu'ils peuvent se battre pour le mutex justement, car j'ai besoin que le mutex soie libre pour que le maître ajoute un élément à la liste ;)
 
Donc je les fait attendre sur le cond, des que cond est vrai, y en a un et un seul qui va passer ( et remettre la cond a false) et prendre le mutex et hopla :)
 
nan ?

Reply

Marsh Posté le 19-10-2003 à 19:42:30    

ben c'est une utilisation canonique. sinon tu risques d'avoir des problèmes. le mutex que tu passe en param, quand la condition est vérifiée il rentre, sinon il le libère. donc sans l'enchassement, ça peut merdoyer

Reply

Marsh Posté le 19-10-2003 à 19:48:45    

exact...
 
Crotte, en plus, je viens de me rendre compte que ca marche pas dans mon cas, faut que je revoie ma condition :(

Reply

Marsh Posté le 19-10-2003 à 19:51:29    

Parce que si j'enchasse, alors forcément il faut que je fasse deux mutex, un pour le maitre, un pour les esclaves...
 
Car si un esclave tiens le mutex, le maitre ne peut le prendre... et donc tlm attends comme des cons, deadock.
 
Donc, il me faut deux mutex ... sur la même liste :??: :??: :??: c'est débile. et ca marchera pas ( deux mutex libérés en meme temps = aie ).
 
La je vois pas comment faire :cry: C'est plus au niveau condition mais au niveau algorithmique la :/

Reply

Marsh Posté le 19-10-2003 à 20:08:13    

j'ai trouvé, me faut un sémaphore, pas moyen autrement.
 
Le semaphore contenant le nombre d'emplacement occupé dans la liste...
 
J'enchaine le sémaphore + le mutex et ca marchera...

Reply

Marsh Posté le 19-10-2003 à 20:22:46    

Voilà le code avec le sémaphore, et ca a l'air d'etre bon :)
 

Code :
  1. /****************************************************************************************/
  2. /***                                       ESCLAVES                                   ***/
  3. /****************************************************************************************/
  4. void* thfunc(void* id)
  5. {
  6.   httpjob* curjob;
  7.   printf("Thread %d\n",id);
  8.   while (1)
  9.     {
  10.       sem_wait(&jlist_sem);
  11.       pthread_mutex_lock(&jlist_mutex);
  12.       curjob = pophead();
  13.       pthread_mutex_unlock(&jlist_mutex);
  14.       printf("thread %d got job %d\n",id,curjob->num);
  15.       free(curjob);
  16.     }
  17. }
  18. /****************************************************************************************/
  19. /***                                   PROCESSUS MAITRE                               ***/
  20. /****************************************************************************************/
  21. int main(char* argv[],int argc)
  22. {
  23.   int i,numjob;
  24.   httpjob* job;
  25.   pthread_t id;
  26.   char* param;
  27.   parseconfig();
  28.   //Initialisation variables globales. Le NULL sert a avoir les attributs par d?éfaut.
  29.   jlist.head = jlist.tail = NULL;
  30.   pthread_mutex_init(&jlist_mutex,NULL);
  31.   sem_init(&jlist_sem,0,0);
  32.   for (i=0;i<5;i++)
  33.     pthread_create(&id,NULL,thfunc,(void*) i);
  34.   printf("Waiting for numbers\n" );
  35.   while (1)
  36.     {
  37.       scanf("%d\n",&numjob);
  38.       job = (httpjob*) malloc (sizeof(httpjob));
  39.       job->num = numjob;
  40.       job->next = NULL;
  41.       pthread_mutex_lock(&jlist_mutex);
  42.       printf("mutex locked\n" );
  43.       addjobinlist(job);
  44.       printf("job added\n" );
  45.       sem_post(&jlist_sem);
  46.       pthread_mutex_unlock(&jlist_mutex);
  47.     }
  48.    
  49.    
  50.   return 1;
  51. }


 
Je sais, c'est du code moche :/

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed