Bonjour à tous
Je débute les threads et j'ai pris pas mal de tutoriels et d'exemples pour essayer de faire les choses simplements. Le programme qui suit est très largement inspiré de F.Hecht.
Voici ce qu'il fait : une tache mère récupère une liste d'instructions à exécuter. A chaque fois qu'un thread lui demande une commande, la tache mère lui donne jsuqu'à ce qu'il n'y ait plus rien à faire. Et c'est là où je cale... mes threads restent bloqués en attente d'une tache. J'ai vu que je pouvais utiliser le "pthread_cond_broadcast" pour réveiller tous les threads d'un coup et donc de leur dire de se terminer, mais je ne vois pas comment faire...
Voici le code, j'espère que vous pourrez m'aider.
Iza

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
179
180
181
182
183
184
185
 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <windows.h>
 
 
#define psleep(sec) Sleep ((sec) * 1000)
 
 
#define NB_THREADS      5
 
struct MaillonToExecute
{
	struct MaillonToExecute *MaillonNext;
	char Commande[80];
};
 
/* Structure stockant les informations des threads et de la tache mère. */
typedef struct
{
    char Commande[80];
	BOOL KillAllThreads;
 
    pthread_t Thread_Mere;
    pthread_t Thread_Fils [NB_THREADS];
 
    pthread_mutex_t Mutex_Commande;
    pthread_cond_t Cond_Commande;
    pthread_cond_t Cond_Exec;
    pthread_cond_t Cond_Die;
}
Threads;
 
static Threads Threads_t ;
 
/* Fonction pour tirer un nombre au sort entre 0 et max. */
int get_random (int max)
{
   double val;
 
   val = (double) max * rand ();
   val = val / (RAND_MAX + 1.0);
 
   return ((int) val);
}
 
 
/* Fonction pour le thread mere. */
void * fn_getliste(void *p_data)
{
	FILE *HandleRun;
	char *FileName="FileCommand.txt";
	char Line[80]=" ";
	char *PtrString;
	struct MaillonToExecute *ListeToExecute,*Maillon,*Ptr;
	BOOL ReadOne=TRUE;
 
	if(HandleRun=fopen(FileName,"rb"))
	{	
		while(fgets(Line,sizeof(Line),HandleRun))
		{
			if(Maillon=(struct MaillonToExecute *)calloc(1,sizeof(struct MaillonToExecute)))
			{
				sprintf(Maillon->Commande,"%s",Line);
				if(PtrString=strchr(Maillon->Commande,'\n')) *PtrString='\0';
				if(PtrString=strchr(Maillon->Commande,'\r')) *PtrString='\0';
				Maillon->MaillonNext=NULL;
				if(ReadOne)
				{
					ListeToExecute=Maillon;
					ReadOne=FALSE;
				}else
				{
					Ptr->MaillonNext=Maillon;
				}
				Ptr=Maillon;	
			}
		}
		fclose(HandleRun);
	}
 
	printf("Fin lecture\n");
	Maillon=ListeToExecute;
	while(Maillon)
	{
	  /* Debut de la zone protegee. */
	  pthread_mutex_lock(&Threads_t.Mutex_Commande);
	  pthread_cond_wait(&Threads_t.Cond_Commande,&Threads_t.Mutex_Commande);
 
	  sprintf(Threads_t.Commande,"%s",Maillon->Commande);
	  printf("Mise a dispo de la %s \n",Threads_t.Commande);
 
	  pthread_cond_signal(&Threads_t.Cond_Exec);
	  pthread_mutex_unlock (&Threads_t.Mutex_Commande);
	  /* Fin de la zone protegee. */
 
	  Ptr=Maillon;
	  Maillon=Maillon->MaillonNext;
	  free(Ptr);
	}
 
	Threads_t.KillAllThreads=TRUE;
 
	pthread_cond_broadcast(&Threads_t.Cond_Die);
	return NULL;
}
 
 
/* Fonction pour les threads. */
void * fn_threads(void *p_data)
{
	int nb=(int)p_data,sec;
 
	printf("Thread %ld\n",nb);
	while(!Threads_t.KillAllThreads)
	{
		/* Debut de la zone protegee. */
		pthread_mutex_lock(&Threads_t.Mutex_Commande);
 
		if(!strncmp(Threads_t.Commande,"\0",1))
		{
			pthread_cond_signal(&Threads_t.Cond_Commande);
			printf("thread %ld demande commande\n",nb);
			pthread_cond_wait(&Threads_t.Cond_Exec,&Threads_t.Mutex_Commande);
			printf("thread %ld continue\n",nb);
		}
		printf("Execution de la %s par thread %ld\n",Threads_t.Commande,nb);
		strncpy(Threads_t.Commande,"\0",1);
		pthread_mutex_unlock(&Threads_t.Mutex_Commande);
		/* Fin de la zone protegee. */
		sec=get_random(10);
		printf("Attente pour thread %ld de %ld secondes\n",nb,sec);
		psleep(sec); 
		printf("Fin attente pour thread %ld\n",nb);
	}
	return NULL;
}
 
 
int main (void)
{
	int i = 0;
	int ret = 0;
 
	pthread_mutex_init(&Threads_t.Mutex_Commande,NULL);
	pthread_cond_init(&Threads_t.Cond_Commande,NULL);
	pthread_cond_init(&Threads_t.Cond_Exec,NULL);
	strncpy(Threads_t.Commande,"\0",1);
	Threads_t.KillAllThreads=FALSE;
 
	/* Creation des threads. */
	printf ("Creation du thread mere !\n");
	ret=pthread_create(&Threads_t.Thread_Mere,NULL,fn_getliste,NULL);
 
	/* Creation des threads si le process mère a fonctionné. */
	if (!ret)
	{
		printf ("Creation des threads fils !\n");
		for (i=0;i<NB_THREADS;i++)
		{
			ret=pthread_create(&Threads_t.Thread_Fils[i],NULL,fn_threads,(void *)i);
			if (ret)
			{
				printf ("%s",strerror(ret));
			}
		}
	}else	
	{
		printf("%s",strerror(ret));
	}
 
 
	/* Attente de la fin des threads. */
	i=0;
	for (i=0;i<NB_THREADS;i++)
	{
		pthread_join(Threads_t.Thread_Fils[i],NULL);
		printf("Fin du thread %ld\n",i);
	}
	pthread_join(Threads_t.Thread_Mere,NULL);
 
	return EXIT_SUCCESS;
}