Hey,

Je bloque sur un exercice qui fait appel à des threads et j'aurais quelques questions.
L'objectif est de faire tracer un carré avec des symboles à différents threads. Et on doit commencer par faire une attente que tous les threads soients prêts avant de démarrer une boucle principale, et je n'arrive pas à le faire en utilisant les conditions posix. L'attente ne fonctionne pas. (voir tentative).
De plus, il faut ensuite que le thread principal envoie quel symbole afficher et combien de fois et que chaque thread va dès lors entrer en compétition pour effectuer les affichages demandés : tant que le symbole doit être encore affiché, le thread doit l’afficher (une seule fois), décrémenter le nombre d’affichages demandés, puis il doit attendre un délai aléatoire avant de recommencer.
J'ai cherché et je n'ai pas compris comment faire ?
Merci d'avance pour l'aide

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
 
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <stdnoreturn.h>
#include <pthread.h>
 
 
#define CHK(op)		do { if ((op) == -1) raler(1, #op); } while (0)
#define CHKN(op)	do { if ((op) == NULL) raler(1, #op); } while (0)
 
#define TCHK(op)	do { if ((errno = (op)) > 0) raler(1, #op); } while (0)
 
noreturn void raler (int syserr, const char *msg, ...)
{
    va_list ap;
 
    va_start (ap, msg);
    vfprintf (stderr, msg, ap);
    fprintf (stderr, "\n");
    va_end (ap);
 
    if (syserr == 1)
	perror ("");
 
    exit (1);
}
 
 
// ----------------------------------------------------
 
struct affichage
{
    char symbole;
    int nb_affichages;
};
 
struct carre
{
    int compteur_cond;  // compteur pour condition 
    int delai_max;      // delai max 
    int n;              // nombre threads
    pthread_cond_t sync;
    pthread_mutex_t verrou;
};
 
// les args de chaque thread
struct arg
{
    int num_threads;	        // donnée privée au thread
    struct carre *carre;		// données partagées
    struct affichage *affichage;// tableau des affichages à réaliser
};
 
 
// retourne un nombre pseudo-aléatoire entre 0 et max (exclu)
int prandom_number (int max, unsigned int *seed) {
    return max * (rand_r (seed) / ((double) RAND_MAX + 1)) ;
}
 
void *afficheur (void *arg) {
    struct arg *a = arg;
    struct carre *carre = a->carre;
    int delai; // délai d'attente aléatoire
    int moi = a->num_threads;  // mon numéro de thread
    int i;
 
    unsigned int seed = moi; // propre au thread + actualisé à chq randr
 
    // Etape 2
    // seed est le numéro du thread
    delai = prandom_number (carre->delai_max, &seed);
    usleep (delai * 1000);	// attente aléatoire en micro-secondes 
 
    pthread_mutex_lock (&carre->verrou);
    // Incrémenter le compteur de threads ayant atteint le point de
    // synchronisation
    carre->compteur_cond++;
 
    // Si tous les threads ne sont pas encore arrivés, 
    // attendre sur la variable conditionnelle
 
    while (carre->compteur_cond < carre->n) {
        pthread_cond_wait (&carre->sync, &carre->verrou);
    }
 
    // Tous les threads sont prêts, débloquer le mutex et continuer
    pthread_mutex_unlock (&carre->verrou);
 
    // Etape 3
    printf ("thread prêt\n");
 
 
    for (i = 0; i<2; i++) {
        printf ("On rentre boucle principale\n");
    }
 
 
 
    return NULL;
}
 
 
 
int main(int argc, char *argv[]) {
 
    int delai_max, nb_threads, taille_cotes, i, delai;
    struct carre carre;		// partagé par tous les joueurs
    pthread_t *tid;                 // tableau des id de threads
    struct arg *targ;               // tableau des args des threads
    //unsigned int seed;
 
    // Vérification de tous arguments
    // Affichage sur sortie standard
    if (argc != 4) 
        raler (0, "usage: carre delai_max nb_threads taille_cote");
 
    delai_max = atoi (argv[1]);
    nb_threads = atoi (argv[2]);
    taille_cotes = atoi (argv[3]);
 
 
    // j'ai mis nb_cotes < 1, car on peut pas faire un carré sinon
    if (delai_max <= 0 || nb_threads < 0 || taille_cotes < 1)
	    raler (0, "argument invalide pour jouer");
 
 
    carre.compteur_cond = 0;
    carre.delai_max = delai_max;
    carre.n = nb_threads;
    TCHK(pthread_cond_init (&carre.sync, NULL));
 
 
    // allocation des tableaus des ids et des args
    CHKN(tid = calloc (nb_threads, sizeof *tid));
    CHKN(targ = calloc (nb_threads, sizeof *targ));
 
 
    // Etape 1 : création des threads
    for (i = 0; i < nb_threads; i++) {
        targ[i].num_threads = i;
        targ[i].carre = &carre;
 
        TCHK(pthread_create (&tid[i], NULL, afficheur, &targ[i]));
    }
 
    // Verrouiller le mutex de la structure carre
    pthread_mutex_lock (&carre.verrou);
 
    // Réinitialiser le compteur de threads
    carre.compteur_cond = 0;
 
    // Envoyer un signal à tous les threads en attente sur 
    // la variable conditionnelle
    pthread_cond_broadcast (&carre.sync);
 
    // Débloquer le mutex de la structure carre
    pthread_mutex_unlock (&carre.verrou);
 
    printf ("debut\n");
 
 
 
 
 
 
    for (i = 0; i < nb_threads; i++) {
	    TCHK(pthread_join (tid[i], NULL));
    }
 
    TCHK(pthread_cond_destroy(&carre.sync));
 
    free (tid) ;
    free (targ) ;
 
 
    exit (0);
}