NOM¶
pthread_cond_init, pthread_cond_destroy, pthread_cond_signal,
pthread_cond_broadcast, pthread_cond_wait, pthread_cond_timedwait -
Opérations sur les conditions
SYNOPSIS¶
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *cond,
pthread_condattr_t *cond_attr);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t
*mutex);
int pthread_cond_timedwait(pthread_cond_t *cond,
pthread_mutex_t *mutex, const struct timespec
*abstime );
int pthread_cond_destroy(pthread_cond_t *cond);
DESCRIPTION¶
Une condition (abréviation pour « variable condition »)
est un mécanisme de synchronisation permettant à un thread de
suspendre son exécution jusqu'à ce qu'une certaine condition (un
prédicat) sur des données partagées soit vérifiée.
Les opérations fondamentales sur les conditions sont : signaler la
condition (quand le prédicat devient vrai) et attendre la condition en
suspendant l'exécution du thread jusqu'à ce qu'un autre thread
signale la condition.
Une variable condition doit toujours être associée à un mutex,
pour éviter une condition concurrente où un thread se prépare
à attendre une condition et un autre thread signale la condition juste
avant que le premier n'attende réellement.
pthread_cond_init() initialise la variable condition
cond, en
utilisant les attributs de condition spécifiés par
cond_attr,
ou les attributs par défaut si
cond_attr vaut
NULL.
L'implémentation LinuxThreads ne supporte aucun attribut de condition,
aussi le paramètre
cond_attr est pour l'instant ignoré.
Les variables de type
pthread_cond_t peuvent également être
statiquement initialisées, en utilisant la constante
PTHREAD_COND_INITIALIZER.
pthread_cond_signal() relance l'un des threads attendant la variable
condition
cond. S'il n'existe aucun thread répondant à ce
critère, rien ne se produit. Si plusieurs threads attendent sur
cond, seul l'un d'entre eux sera relancé, mais il est impossible
de savoir lequel.
pthread_cond_broadcast() relance tous les threads attendant sur la
variable condition
cond. Rien ne se passe s'il n'y a aucun thread
attendant sur
cond.
pthread_cond_wait() déverrouille atomiquement le
mutex (comme
pthread_unlock_mutex()) et attend que la variable condition
cond
soit signalée. L'exécution du thread est suspendue et ne consomme
pas de temps CPU jusqu'à ce que la variable condition soit signalée.
Le
mutex doit être verrouillé par le thread appelant à
l'entrée de
pthread_cond_wait(). Avant de rendre la main au thread
appelant,
pthread_cond_wait() reverrouille
mutex (comme
pthread_lock_mutex()).
Le déverrouillage du mutex et la suspension de l'exécution sur la
variable condition sont liés atomiquement. Donc, si tous les threads
verrouillent le mutex avant de signaler la condition, il est garanti que la
condition ne peut être signalée (et donc ignorée) entre le
moment où un thread verrouille le mutex et le moment où il attend
sur la variable condition.
pthread_cond_timedwait() déverrouille le
mutex et attend sur
cond, en liant atomiquement ces deux étapes, comme le fait
pthread_cond_wait(), cependant l'attente est bornée
temporellement. Si
cond n'a pas été signalée après
la période spécifiée par
abstime, le mutex
mutex
est reverrouillé et
pthread_cond_timedwait() rend la main avec
l'erreur
ETIMEDOUT. Le paramètre
abstime spécifie un
temps absolu, avec la même origine que
time(2) et
gettimeofday(2) : un
abstime de 0 correspond à
00:00:00 GMT, le 1er Janvier 1970.
pthread_cond_destroy() détruit une variable condition, libérant
les ressources qu'elle possède. Aucun thread ne doit attendre sur la
condition à l'entrée de
pthread_cond_destroy(). Dans
l'implémentation LinuxThreads, aucune ressource ne peut être
associée à une variable condition, aussi
pthread_cond_destroy() ne fait en fait rien d'autre que vérifier
qu'aucun thread n'attend la condition.
ANNULATION¶
pthread_cond_wait() et
pthread_cond_timedwait() sont des points
d'annulation. Si un thread est annulé alors qu'il est suspendu dans l'une
de ces fonctions, son exécution reprend immédiatement,
reverrouillant le paramètre
mutex à
pthread_cond_wait() et
pthread_cond_timedwait(), et exécute
finalement l'annulation. Aussi, les gestionnaires d'annulation sont
assurés que
mutex est verrouillé lorsqu'ils sont
exécutés.
ASYNC-SIGNAL SAFETY¶
Ces fonctions ne sont pas fiables par rapport aux signaux asynchrones et ne
doivent donc pas être utilisées dans des gestionnaires de signaux
[NdT : sous peine de perdre leur propriété d'atomicité].
En particulier, appeler
pthread_cond_signal() ou
pthread_cond_broadcast() dans un gestionnaire de signal peut placer le
thread appelant dans une situation de blocage définitif.
VALEUR RENVOYÉE¶
Toutes ces fonctions renvoient 0 en cas de succès et un code d'erreur non
nul en cas de problème.
ERREURS¶
pthread_cond_init(),
pthread_cond_signal(),
pthread_cond_broadcast() et
pthread_cond_wait() ne renvoient
jamais de code d'erreur.
La fonction
pthread_cond_timedwait() renvoie l'un des codes d'erreur
suivants en cas de problème :
- ETIMEDOUT
- La variable condition n'a pas reçu de signal avant le
délai spécifié par abstime.
- EINTR
- pthread_cond_timedwait() a été interrompu
par un signal.
La fonction
pthread_cond_destroy() renvoie le code d'erreur suivant en
cas de problème :
- EBUSY
- Il existe des threads attendant cond.
AUTEUR¶
Xavier Leroy <Xavier.Leroy@inria.fr>
VOIR AUSSI¶
pthread_condattr_init(3),
pthread_mutex_lock(3),
pthread_mutex_unlock(3),
gettimeofday(2),
nanosleep(2)
EXEMPLE¶
Considérons deux variables globales partagées
x et
y,
protégées par le mutex
mut, et une variable condition
cond pour signaler que
x devient plus grand que
y.
int x,y;
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
Attendre que
x devienne plus grand que
y se réalise de la
manière suivante :
pthread_mutex_lock(&mut);
while (x <= y) {
pthread_cond_wait(&cond, &mut);
}
/* operate on x and y */
pthread_mutex_unlock(&mut);
Les modifications de
x et
y qui peuvent rendre
x plus grand
que
y doivent signaler la condition si nécessaire :
pthread_mutex_lock(&mut);
/* modify x and y */
if (x > y) pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);
S'il peut être prouvé qu'au plus un thread en attente nécessite
d'être réveillé (par exemple, s'il n'y a que deux threads
communiquant via
x et
y),
pthread_cond_signal() peut
être utilisé en tant qu'alternative efficace à
pthread_cond_broadcast(). En cas de doute, utilisez
pthread_cond_broadcast().
Pour attendre que
x devienne plus grand que
y avec un délai
de 5 secondes, faîtes :
struct timeval now;
struct timespec timeout;
int retcode;
pthread_mutex_lock(&mut);
gettimeofday(&now);
timeout.tv_sec = now.tv_sec + 5;
timeout.tv_nsec = now.tv_usec * 1000;
retcode = 0;
while (x <= y && retcode != ETIMEDOUT) {
retcode = pthread_cond_timedwait(&cond, &mut, &timeout);
}
if (retcode == ETIMEDOUT) {
/* timeout occurred */
} else {
/* operate on x and y */
}
pthread_mutex_unlock(&mut);
TRADUCTION¶
Cette page de manuel a été traduite par Thierry Vignaud <tvignaud
AT mandriva DOT com> en 2000 et révisée par Alain Portal
<aportal AT univ-montp2 DOT fr> en 2006. La version présente dans
Debian est maintenue par les membres de la liste <debian-l10n-french AT
lists DOT debian DOT org>. Veuillez signaler toute erreur de traduction par
un rapport de bogue sur le paquet manpages-fr-extra.