pthread_cond_init - ライブラリコールの説明 - Linux コマンド集 一覧表
NAME
pthread_cond_init, pthread_cond_destroy, pthread_cond_signal, pthread_cond_broadcast, pthread_cond_wait, pthread_cond_timedwait - 条件変数の操作
書式
#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
);
説明
条件(「条件変数」の省略) は、共有データに対するある述語が満たされる
まで、スレッドが実行を停止しプロセッサを手放すことを可能にする同期
装置である。条件に対する基本的な操作は、(述語が真になった場合に)
条件を送信することと、他のスレッドが条件を送信するまでスレッドの実行
を停止して条件を待つことである。
条件変数はいつでも mutex と結びつけられていなければならない。これは、
あるスレッドが条件変数を待とうとしている時に、他のスレッドが、
先のスレッドが実際に条件変数に対して待機するその直前に条件を送信する、
という競合条件を避けるためである。
"pthread_cond_init"
は、条件変数
cond
を
cond_attr
で指定された条件属性、または
"cond_attr"
が
NULL
であれば、デフォルトの属性で初期化する。
LinuxThreads の実装は、いかなる条件変数の属性にも対応していない。
かくして、
"cond_attr"
パラメタは、実のところ無視される。
型
"pthread_cond_t"
の変数は、定数
PTHREAD_COND_INITIALIZER
を使って静的に初期化することもできる。
"pthread_cond_signal"
は、条件変数
cond
に備えて待機しているスレッドの一つの実行を再開させる。
cond
を待っているスレッドがなければ、何も起こらない。
複数のスレッドが
cond
を待っていれば、ただ一つのものだけが再開されるが、どれであるかは
わからない。
"pthread_cond_broadcast"
は
cond
に備えて待機している全てのスレッドの実行を再開させる。
cond
を待っているスレッドがなければ、何も起こらない。
"pthread_cond_wait"
は
(
pthread_mutex_unlock
による)
"mutex"
のアンロックと条件変数
"cond"
の送信に対する待機を一息で行う。条件変数が送信されるまで
スレッドの実行は停止され、CPU 時間を消費することはない。
"mutex"
は、
pthread_cond_wait
の開始時点で、これを呼び出すスレッドによってロックされていなければ
ならない。
呼び出し側のスレッドに戻る前に
"pthread_cond_wait"
は
"mutex"
を
(
pthread_mutex_lock
によって)再び獲得する。
mutex のアンロックと条件変数に対する待機は一息に行われる。従って、
全てのスレッドが条件を送信する前に常に mutex を獲得するのならば、
スレッドが mutex をアンロックする時点と、それが条件変数を待つ時点
との中間の時点で、条件の送信が行なわれる(従って無視される)ことが
不可能となることが保証される。
"pthread_cond_timedwait"
は
"pthread_cond_wait"
と同じく、一息で
"mutex"
のアンロックと
cond
への待機を行う。しかしまた、待ち時間の長さの設定も行う。
"cond"
が
abstime
で指定された時間内に送信されなかったのならば、
mutex
"mutex"
が再獲得され
"pthread_cond_timedwait"
は、エラー
ETIMEDOUT
を返す。
"abstime"
パラメタは
time
(2) と
gettimeofday
(2) の起点を同じくする絶対時間を指定する。すなわち
0 の
"abstime"
は 00:00:00 GMT, January 1, 1970 に相当する。
"pthread_cond_destroy"
は条件変数を破壊し、それが保持している可能性のある資源を開放する。
pthread_cond_destroy
の開始時点で、いかなるスレッドもその条件変数を待っていてはいけない。
LinuxThreads の実装では、いかなる資源も条件変数に付随していない。
従って、
"pthread_cond_destroy"
は、条件が待機スレッドを持っていないことを確かめる以外に
何もしない。
取り消し
"pthread_cond_wait"
および
"pthread_cond_timedwait"
は、取り消しポイントである。このいずれかの関数で停止している
スレッドが取り消されると、スレッドは直ちに実行を再開し、
"pthread_cond_wait"
と
pthread_cond_timedwait
の
"mutex"
引数を再ロックし、最後に取り消しを実行する。
結果として、クリーンアップハンドラが呼び出される際に
"mutex"
がロックされていることを保証される。
非同期シグナルに対する安全性
条件関数は非同期シグナルに対して安全ではない。よって、
シグナルハンドラから呼び出すべきではない。特に、
"pthread_cond_signal"
または
"pthread_cond_broadcast"
のシグナルハンドラからの呼び出しは、呼び出しスレッドを
デッドロックする可能性がある。
返り値
全ての条件変数関数は、成功すると 0 を返し、エラーならば非ゼロの
エラーコードを返す。
エラー
pthread_cond_init
,
pthread_cond_signal
,
pthread_cond_broadcast
,および
"pthread_cond_wait"
は、決してエラーコードを返さない。
"pthread_cond_timedwait"
は、エラーに際して次のエラーコードを返す:
- "ETIMEDOUT"
-
条件変数が
"abstime"
で指定された時限までに送信されなかった。
- "EINTR"
-
"pthread_cond_timedwait"
がシグナルによって割り込まれた。
"pthread_cond_destroy" 関数は、エラーに際して次のエラーコードを返す:
- "EBUSY"
-
いずれかのスレッドが現在
cond
に対して待機している。
著者
Xavier Leroy <Xavier.Leroy@inria.fr>
関連項目
pthread_condattr_init
(3),
pthread_mutex_lock
(3),
pthread_mutex_unlock
(3),
gettimeofday
(2),
nanosleep
(2).
例
二つの共有変数
"x"
と
y
があって、mutex
mut
により保護されているとしよう。更に、条件変数
"cond"
があって、
"x"
が
y
より大きくなれば、送信されるとしよう。
int x,y; pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
"x" が "y" より大きくなるまで待つには、 次のようにすれば良い:
pthread_mutex_lock(&mut); while (x <= y) { pthread_cond_wait(&cond, &mut); } /* x と y の操作 */ pthread_mutex_unlock(&mut);
"x" を "y" よりも大きくするような "x" と "y" の操作は必要に応じて、条件を送信せねばならない:
pthread_mutex_lock(&mut); /* x と y を変更する */ if (x > y) pthread_cond_broadcast(&cond); pthread_mutex_unlock(&mut);
起動すべきスレッドが最大限一つであることが確実ならば
(例えば、
"x"
と
y
を通じて交流するスレッドが二つしかないのならば)、
"pthread_cond_signal"
を
pthread_cond_broadcast
の、少しばかり効率的な代替物として使用できる。
疑問のある場合には
pthread_cond_broadcast
を使用せよ。
"x"
が
"y"
より大きくなるのを五秒の時限を設けて待つには次のようにする:
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) { /* タイムアウト */ } else { /* x と y の操作 */ } pthread_mutex_unlock(&mut);