Bpnjour à tous,

J'ai posté ce message sur un autre site mais je n'arrive pas à avoir certaines précisions sur les thread.

j'ai trouvé ce code et j'essaie de le comprendre

voici le code

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
 
#include <windows.h>
#define psleep(sec) Sleep((sec)*1000)
 
#if defined(Win32)
  #include <windows.h>
  #define psleep(sec) Sleep((sec)*1000)
#elif defined(Linux)
  #include <unistd.h>
  #define psleep(sec)sleep((sec))
#endif
 
#define STOCK_INITIAL 20
#define NOMBRE_CLIENT 5
 
 
/* http://franckh.developpez.com/tutoriels/posix/pthreads/ */
 
 
/* Structure stockant les informations des threads clients et du magasin */
typedef struct S_Magasin S_Magasin;
 
struct S_Magasin
{
  int S_Magasin_Fin[NOMBRE_CLIENT];
  int S_Magasin_Stock;
 
  pthread_t S_Magasin_Thread_Magasin;
  pthread_t S_Magasin_Thread_Client[NOMBRE_CLIENT];
 
  pthread_mutex_t S_Magasin_Mutex_S_Magasin_Stock;
  pthread_cond_t S_Magasin_Condition_S_Magasin_Stock;
  pthread_cond_t S_Magasin_Condition_Client;
};
 
static S_Magasin s_magasin=
{
  .S_Magasin_Fin=0,
  .S_Magasin_Stock=STOCK_INITIAL,
  .S_Magasin_Mutex_S_Magasin_Stock=PTHREAD_MUTEX_INITIALIZER,
  .S_Magasin_Condition_S_Magasin_Stock=PTHREAD_COND_INITIALIZER,
  .S_Magasin_Condition_Client=PTHREAD_COND_INITIALIZER,
};
 
 
/* Fonction pour tirer un nombre au sort entre 0 et nombre_maximum */
static int fonction_generer_nombre_aleatoire(int nombre_maximum)
{
   double nombre_aleatoire;
 
   nombre_aleatoire=(double)nombre_maximum*rand();
   nombre_aleatoire= nombre_aleatoire/(RAND_MAX+1.0);
 
   return((int)nombre_aleatoire);
}
 
 
/* Fonction pour le thread du magasin */
 
/* Le thread attendant que la condition soit remplie pour s'activer, nous n'avons plus besoin du test
   à l'intérieur de la boucle, nous pouvons donc directement remplir le stock. Nous pouvons voir un processus
   particulier en ce qui concerne les conditions. En effet, si on regarde le début du corps de la boucle,
   on peut s'apercevoir que le thread prend le mutex et se met en attente de la condition. En réalité,
   le thread relâche le mutex aussitôt et le reprend automatiquement lorsque la condition est vraie
   et qu'il soit réveillé par un autre thread. Lorsque la stock est remplit, la fonction le signale au thread
   du client courant. */
 
static void* fonction_magasin(void *p_donnee)
{
  while(1)
  {
    /* Debut de la zone protegee */
    pthread_mutex_lock(&s_magasin.S_Magasin_Mutex_S_Magasin_Stock);
    pthread_cond_wait(&s_magasin.S_Magasin_Condition_S_Magasin_Stock,&s_magasin.S_Magasin_Mutex_S_Magasin_Stock);
 
    s_magasin.S_Magasin_Stock=STOCK_INITIAL;
    printf("Remplissage du stock du magasin de %d articles !\n",s_magasin.S_Magasin_Stock);
 
    pthread_cond_signal(&s_magasin.S_Magasin_Condition_Client);
    pthread_mutex_unlock(&s_magasin.S_Magasin_Mutex_S_Magasin_Stock);
    /* Fin de la zone protegee. */
  }
 
  return NULL;
}
 
 
/* Fonction pour les threads des clients */
 
/* Cette fonction a aussi eu droit à un petit lifting. En effet, un test a été rajouté qui permet
   de déterminer si le stock est en quantité suffisante par rapport à la demande du client.
   Si ce n'est pas le cas, le thread le signal au thread du magasin qui prend le relais,
   le thread appelant ce met en attente le temps que le magasin réalise sa tâche. */
 
static void* fonction_client(void *p_donnee)
{
  int client_nombre_pris_sur_stock=0;
  int client_numero=(int)p_donnee;
 
  while(s_magasin.S_Magasin_Fin[client_numero]<3)
  {
    client_nombre_pris_sur_stock=fonction_generer_nombre_aleatoire(5);
 
    psleep(fonction_generer_nombre_aleatoire(2));
 
    /* Debut de la zone protegee */
    pthread_mutex_lock(&s_magasin.S_Magasin_Mutex_S_Magasin_Stock);
 
    if(client_nombre_pris_sur_stock>s_magasin.S_Magasin_Stock)
    {
      pthread_cond_signal(&s_magasin.S_Magasin_Condition_S_Magasin_Stock);
      pthread_cond_wait(&s_magasin.S_Magasin_Condition_Client,&s_magasin.S_Magasin_Mutex_S_Magasin_Stock);
 
      s_magasin.S_Magasin_Fin[client_numero]++;
    }
    else
    {
      s_magasin.S_Magasin_Stock-=client_nombre_pris_sur_stock;
 
      printf("Le client => %d, prend %d du stock,reste %d en stock !\n",client_numero,client_nombre_pris_sur_stock,s_magasin.S_Magasin_Stock);
    }
 
    pthread_mutex_unlock(&s_magasin.S_Magasin_Mutex_S_Magasin_Stock);
    /* Fin de la zone protegee */
  }
 
  return NULL;
}
 
 
int main(int argc,char *argv[])
{
  int i=0;
  int thread_magasin_retour=0;
  int thread_client_retour=0;
  void** pp_thread_magasin_join=NULL;
 
  /* Creation des threads. */
  printf("Creation du thread du magasin !\n");
  thread_magasin_retour=pthread_create(&s_magasin.S_Magasin_Thread_Magasin,NULL,fonction_magasin,NULL);
 
  /* Creation des threads des clients si celui du magasinn a reussi. */
  if(!thread_magasin_retour)
  {
    printf("Creation des threads clients !\n");
 
    for(i=0;i<NOMBRE_CLIENT;i++)
    {
      thread_client_retour=pthread_create(&s_magasin.S_Magasin_Thread_Client[i],NULL,fonction_client,(void*)i);
 
      if(thread_client_retour)
      {
        fprintf(stderr,"%s",strerror(thread_client_retour));
      }
    }
  }
  else
  {
    fprintf(stderr,"%s",strerror(thread_magasin_retour));
  }
 
  /* Attente de la fin des threads. */
 
  for(i=0;i<NOMBRE_CLIENT;i++)
  {
    pthread_join(s_magasin.S_Magasin_Thread_Client[i],NULL);
  }
 
  pthread_join(s_magasin.S_Magasin_Thread_Magasin,pp_thread_magasin_join);
 
  pthread_exit(pp_thread_magasin_join);
 
  return EXIT_SUCCESS;
}
j'aimerais savoir si mon raisonnement suivant et bon

dans main je crée le thread magasin, il est initialisé à PTHREAD_MUTEX_FAST_NP
j'appelle la fonction qui lui est associé

la je mets un mutex sur la variable du stock du magasin

pthread_mutex_lock(&s_magasin.S_Magasin_Mutex_S_Magasin_Stock);

, puisqu'elle n'est pas verouillé, elle est verouillé par le thread appelant qui est le thread magasin
puis arrive le cond_wait, qui dévérouille le mutex, là, le thread magasin, attend le signal envoyé par les thread clients, pour que la condition

&s_magasin.S_Magasin_Condition_S_Magasin_Stock

, qu'attend le thread magasin soit signalé pr un des thread clients.

à peu près en même temps, les thread clients sont crées un à un, ils sont initialisés à PTHREAD_MUTEX_FAST_NP, leur identifiant,respectif, est mis dans la variable
S_Magasin_Thread_Client[NOMBRE_CLIENT];

chaque thread client, mets un mutex sur

pthread_mutex_lock(&s_magasin.S_Magasin_Mutex_S_Magasin_Stock);

là je teste si il reste assez de stock pour satisfaire le client,

si oui
j'enlève du stock ce qui est pris par ce client
et je dévérouille
pthread_mutex_unlock(&s_magasin.S_Magasin_Mutex_S_Magasin_Stock);

et je continue jusqu'à ce que le stock ne soit pas suffisant pour satisfaire un des clients

et là j'ai

si oui

j'envoie le signal au thread magasin, pour lui dire ta condition est remplie
pthread_cond_signal(&s_magasin.S_Magasin_Condition_S_Magasin_Stock);

puis le thread client se met en attente du signal par le thread magasin que le stock a été refait
et dévérouille &s_magasin.S_Magasin_Mutex_S_Magasin_Stock
pthread_cond_wait(&s_magasin.S_Magasin_Condition_Client,&s_magasin.S_Magasin_Mutex_S_Magasin_Stock);

je reprends mon thread magasin
&s_magasin.S_Magasin_Mutex_S_Magasin_Stock est donc dévérouillé, donc le thread magasin
remplie le stock

puis le thread magasin dit au thread client que la condition est remplie
et il dévérouille

&s_magasin.S_Magasin_Mutex_S_Magasin_Stock
mis par lui même

et se revérouille
&s_magasin.S_Magasin_Mutex_S_Magasin_Stock

et se met en attente à nouveau

je reprends le thread client
il dévérouille

&s_magasin.S_Magasin_Mutex_S_Magasin_Stock
mis par lui même

et recommence à enlever du stock par les clients

maintenant j'aimerais faire une action par exemple pour 3 remplissages de stock on arrête tout
et là, je rame, je n'arrive plus à comprendre comment faire avec les 2 attentes réciproques des thread, et leur signal que chacun, thread magasin et les thread clients, s'envoient les uns à l'autre

c'est là que j'ai du mal avec la pratique pour savoir qui commande l'autre,

faut il faire un

pthread_cancel(pthread_t thread);

et où

dans le thread magasin sur tous les thread clients ou
dans le thread client pour chaque client sur le thread magasin

merci d'avance