Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

pthread_cond_* en particulier pthread_cond_signal !

6 réponses
Avatar
Machine
Hello, j'aurais besoin d'un petit coup de main pour placer pthread_cond_sig=
nal dans le code suivant... je d=E9bute avec les threads et ne pas de solut=
ion...

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define MAX 8

struct list {
int i;
struct list *next;
pthread_mutex_t mutex_zone;
pthread_cond_t condition;
};

struct list *init(void) {
struct list *p =3D malloc(sizeof(struct list));
p->i =3D 0;
p->next =3D NULL;
return p;
}

struct list stack =3D {
.i =3D 0,
.next =3D NULL,
.mutex_zone =3D PTHREAD_MUTEX_INITIALIZER,
.condition =3D PTHREAD_COND_INITIALIZER
};

void print(struct list *p)
{
printf("%d %p\n", p->i, p->next);
}

void push(struct list *p)
{
int i =3D 0;
pthread_mutex_lock(&stack.mutex_zone);
while(i !=3D 1000) {
pthread_cond_wait(&stack.condition, &stack.mutex_zone);
p =3D &stack;
p->i +=3D 1;
p->next =3D init();
print(p);
if(i++) {
pthread_cond_signal(&stack.condition);
}
}
pthread_mutex_unlock(&stack.mutex_zone);
}

void pop(/* next time */);

int main(void)
{
struct list *l =3D init();
pthread_t t[MAX];
int i =3D 0;
while(i++ < MAX) pthread_create(&t[i], NULL, (void *) push, (void *) l)=
;
for(i =3D 0; i < MAX; i++) pthread_join(t[i], NULL);
return 0;
}

Cordialement

6 réponses

Avatar
Cyprien Nicolas
Salut,

Le 27/09/2013 13:40, Machine écrivit :
Hello, j'aurais besoin d'un petit coup de main pour placer
pthread_cond_signal dans le code suivant... je débute avec
les threads et ne pas de solution...



Ça ressemble à un TP de programmation parallèle.

Je n'ai pas testé le programme, car je vois une erreur de logique dans
ton main() :

int main(void)
{
struct list *l = init();
pthread_t t[MAX];
int i = 0;
while(i++ < MAX) pthread_create(&t[i], NULL, (void *) push, (void *) l);
for(i = 0; i < MAX; i++) pthread_join(t[i], NULL);
return 0;
}



Ton while (i++ < MAX), t[i]… peut pas être correct, vu que
l'incrément se fait dans le test du while, i vaudra 1 dans le corps de
la boucle, du coup t[0] n'est jamais initialisé.

Soit tu fais un for() comme en-dessous, soit plutôt un do-while avec
préincrément, ou tu déplaces le post-incrément sur la dernière
utilisation du i.

do {
pthread_create(&t[i], NULL, (void *) push, (void *) l);
} while(++i < MAX);

ou alors :

while(i < MAX) pthread_create(&t[i++], NULL, (void *) push, (void *) l);


Mais je trouve cette dernière pas géniale car le ++ est /caché/ dans le
corps de la boucle.

--
Cyp
Avatar
Machine
Le vendredi 27 septembre 2013 15:49:56 UTC+2, Cyprien Nicolas a écrit :

Sans vouloir faire d'histoire, l'objet du post est d'abord la fonction push et en particulier les fonctions pthreads_cond_*... en testant le code vous auriez compris que do/while ou for(;;) ne le debug pas...
Avatar
Cyprien Nicolas
Le 27/09/2013 19:00, Machine écrivit :
Le vendredi 27 septembre 2013 15:49:56 UTC+2, Cyprien Nicolas a
écrit :

Sans vouloir faire d'histoire, l'objet du post est d'abord la
fonction push et en particulier les fonctions pthreads_cond_*... en
testant le code vous auriez compris que do/while ou for(;;) ne le
debug pas...



Ah ben après coup j'ai testé, et ça segfault dans le for(), donc si, il
y a bien un problème à cet endroit là.

Le reste du programme dans le push me semble correct, l'objet du post ne
mentionnait pas pourquoi ça marche pas, en décrivant le comportement
attendu, et le comportement constaté, il m'est difficile d'aider plus avant.

PS: vos lignes sont un peu longues…

--
« Ceci n'est pas une signature. » — René Magritte (Apocryphe)
Avatar
Lucas Levrel
Le 27 septembre 2013, Machine a écrit :

Hello, j'aurais besoin d'un petit coup de main pour placer
pthread_cond_signal dans le code suivant... je débute avec les threads
et ne pas de solution...



Normalement un cond_wait est dans un while(!macondition). Renseigne-toi
sur les « spurious wakeups ».

--
LL
Avatar
Machine
Chez moi:

int main(void)
51 {
52 struct list *l = init();
53 pthread_t t[MAX];
54 int i = 0;
55 /* while(i++ < MAX) pthread_create(&t[i], NULL, (void *) push, (void *) l); */
56 do {
57 pthread_create(&t[i], NULL, (void *) push, (void *) l);
58 } while(++i < MAX);
59
60 for(i = 0; i < MAX; i++) pthread_join(t[i], NULL);
61 return 0;
62 }
63

n'arrange rien...
Avatar
Richard Delorme
Le 27/09/2013 13:40, Machine a écrit :
void push(struct list *p)
{
int i = 0;
pthread_mutex_lock(&stack.mutex_zone);
while(i != 1000) {
pthread_cond_wait(&stack.condition, &stack.mutex_zone);



le programme bloque ici... le reste n'ai jamais exécuté

p = &stack;
p->i += 1;
p->next = init();
print(p);
if(i++) {
pthread_cond_signal(&stack.condition);



le signal doit être envoyé depuis un autre thread.

}
}
pthread_mutex_unlock(&stack.mutex_zone);
}



Voici un exemple qui marche :

/* j'ai un pool de tâche qui someillent et que je réveille à la demande */

/* une boucle infini ou sommeille une tâche (task) */
void* task_loop(void *param)
{
Task *task = (Task*) param;

lock(task->mutex);
task->loop = true;

while (task->loop) {
if (!task->run) {
condition_wait(task->cond);
}
if (task->run) {
task_search(task);
task_stack_put_idle_task(task->container, task);
}
}

unlock(task->mutex);

return NULL;
}


/* dans un autre thread, l'action qui réveille la tâche */
if ((task = task_stack_get_idle_task(tasks)) != NULL) {
task_init(task);

lock(task->mutex);
task->run = true;
condition_signal(task->cond);
unlock(task->mutex);
}


les lock/unlock/condition_wait et condition_signal sont des macros qui
lancent les fonctions pthread ou leur équivalent windows selon l'OS ou
la bibliothèque utilisée.

--
Richard