pthread_create()
新規にスレッドを作成します。
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);
pthread_create()
は、現在実行中のプロセス内で、attrで指定した属性を持ったスレッドを新規に作成します。新しく出来たスレッドは、start_routine()
から実行を開始します。スレッドが正常に作成出来た時は、threadにスレッドIDを格納します。
特に個別に属性を指定する必要が無い時は、attrにNULLを指定する事が出来ます。attrにNULLを指定した場合、デフォルトの属性が指定された事になります。デフォルトの属性とは、pthread_attr_init()
で初期化した後、何の処理も行っていない状態の属性オブジェクトを指定した状態を指します。
新しく出来たスレッドが実行を開始するstart_routine()
は、1つのvoid *
型の引数を取ります。また、void *
型の返り値を取る事が出来ます。複数の引数や返り値を扱いたい場合には、配列や構造体のポインタをvoid *
型にキャストして与えるといいでしょう。その時に注意すべき事は、当然ながらstart_routine()
の内部で使っていたローカル変数のポインタを返り値として渡そうとしても、start_routine()
から出た途端に無効になってしまいます。
start_routine()
から返る事は、pthread_exit()
の引数にスレッドの返り値を与えて呼び出す事と等価です。但しmain()
自身の場合は、pthread_exit()
では無くexit()
になります。
pthread_create()
が成功した時には0を返します。他の場合は、以下に示す通りのエラーに応じた値を返します。
システムが新しくスレッドを作る為に必要なリソースが足りません。または、システムが作成出来るスレッドの最大個数を超えてしまった為に、スレッドを作る事が出来ませんでした。システムが作る事が出来るスレッドの最大個数は、定数PTHREAD_THREADS_MAXに定義されています。
attrが不正な値です。
pthread_create()
呼び出した側に、スケジューリングパラメタやスケジューリングポリシーを設定する権限がありません。
pthread_create()
は、エラーコード[EINTR]で返る事はありません。
pthread_exit()
スレッドを終了します。
void pthread_exit(void *value_ptr);
pthread_exit()
は、現在実行しているスレッド自身を終了します。value_ptrには、スレッドの終了に伴う返り値をセットします。
スレッドの終了に伴って、以下に示す事が順番に実行されます。
登録されていれば、キャンセルハンドラが実行されます。複数のキャンセルハンドラを登録している場合は、最後に登録された物から順番に実行されます。
スレッドにスレッド固有データがあれば、スレッド固有データのデストラクタが実行されます。デストラクタの実行順序は特に決まっていません。
スレッドが起動したエントリポイントであるスタートルーチンから返ってきた時、つまりスレッドが終了した時に、暗黙の内にpthread_exit()
が呼ばれます。但し、main()
自身であるスレッドを除きます。このmain()
自身であるスレッドというのは、main()
が実行を開始した直後に唯一実行しているスレッドを指します。
pthread_exit()
を呼び出した事により、副次的に呼び出されたキャンセルハンドラやスレッド固有データのデストラクタから、再度pthread_exit()
が呼び出された時の動作は未定義です。
pthread_exit()
が正常に実行し終わり、スレッドが終了した後に、そのスレッドのローカル変数にアクセスした時の動作は未定義です。これに伴って、スレッドのローカル変数への参照をpthread_exit()
の返り値に利用する事は非常に危険です。
全てのスレッドが終了すると、プロセスはシステムに0を返して終了します。これは、exit()
の引数に0を指定した時の動作と同じです。
返り値がvoid
型なので、返り値はありません。
pthread_exit()
はエラーを起こしません。また、pthread_exit()
は、エラーコード[EINTR]で返る事はありません。
pthread_join()
スレッドが終了するまでブロックします。
int pthread_join(pthread_t thread, void **value_ptr);
pthread_join()
は、threadで指定したスレッドが終了するまで実行を一時停止します。既にthreadで指定したスレッドが終了していた時は、何も起こりません。value_ptrにvoid
型のポインタのポインタを指定すると、pthread_exit()
から渡されたスレッドの返り値をvalue_ptrが参照する変数に格納します。value_ptrにNULLを指定すると、返り値はどこにも格納されません。pthread_join()
が正常に終了したという事は、スレッドが既に終了しているという事です。
同時に複数のpthread_join()
が同じスレッドに対して呼ばれた時の結果は未定義です。pthread_join()
の呼び出し中にキャンセルが発生した場合、スレッドはまだ動いています。
pthread_join()
が成功した時には0を返します。他の場合は、以下に示す通りのエラーに応じた値を返します。
pthread_detach()
スレッドのメモリを回収してよい事を宣言します。
int pthread_detach(pthread_t thread);
pthread_detach()
は、threadが示すスレッドIDのスレッドが終了した時に、そのスレッドのメモリを回収してもよい事を宣言します。threadが示すスレッドがまた終了していない場合、そのスレッドを強制的に終了する事はありません。1つのスレッドに対して複数回pthread_detach()
を呼び出した時の結果は未定義です。
pthread_detach()
が成功した時には0を返します。他の場合は、以下に示す通りのエラーに応じた値を返します。
pthread_equal()
2つのスレッドIDを比較します。
int pthread_equal(pthread_t t1, pthread_t t2);
2つのスレッドIDt1, t2を比較します。
t1とt2が等しい時は非0値が返ります。等しくない時は0が返ります。
pthread_equal()
はエラーを起こしません。また、pthread_equal()
は、エラーコード[EINTR]で返る事はありません。
pthread_once()
一度だけ関数が呼ばれるようにする為の枠組みを提供します。
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
pthread_once()
は、主に初期化の為に一度だけ呼ばれる関数を使う時、その一度だけ呼ばれる機能を提供します。
最初にpthread_once()
にonce_controlと、初期化の為の関数init_routineを与えると、init_routine()
が実行されます。pthread_once()
から返って来た時にはinit_routine()
の実行が完了している事が保証されます。引数の宣言からも明らかな通り、init_routine()
は引数を取る事が出来ません。
2回目以降に、同じ引数をpthread_once()
に与えて呼びだすと、今度はinit_routine()
を呼び出しません。
once_controlは、init_routine()
が既に呼び出されたかどうかを判断する為に使われています。なので、同じ関数のポインタをinit_routineに与えても、once_controlに同じ物を使わないと、init_routine()
がもう一度呼ばれてしまいます。
pthread_once()
を使用する手順は、以下の様になります。
pthread_once_t
型の変数にPTHREAD_ONCE_INITを代入して、初期化します。pthread_once_t
型の変数をonce_control、初期化する為の関数をinit_routineを指定してpthread_once()
を呼び出します。するとinit_routineが呼び出されます。pthread_once()
をもう一度呼び出すと、何も起こりません。PTHREAD_ONCE_INITはpthread.hで定義されています。
pthread_once()
はキャンセルポイントではありません。init_routineがキャンセルポイントだった時、それがキャンセルされるとonce_controlにinit_routine()
を呼び出した事を記録する前にキャンセルされ、あたかもpthread_once()
が呼ばれていないかのようになってしまう為です。
pthread_once()
が成功した時には0を返します。他の場合は、エラーに応じた値を返します。と仕様上はなっていますが、以下に示す通り、phread_once()
はエラーで返る事はありません。
pthread_once()
はエラーを起こしません。また、pthread_once()
は、エラーコード[EINTR]で返る事はありません。
pthread_self()
スレッドIDを取得します。
pthread_t pthread_self(void);
現在実行中のスレッドIDを取得します。pthread_create
でスレッドを作成した側は、実行中のスレッドIDを知っていますが、実行している側は引数にスレッドIDを含めるなどの方法をとらない限り、スレッドIDを取得する事は出来ません。なので、普通はpthread_self()
を用いてスレッドIDを取得します。
スレッドIDを返します。
pthread_self()
はエラーを起こしません。また、pthread_self()
は、エラーコード[EINTR]で返る事はありません。
void pthread_cleanup_push(void (*routine)(void*), void *arg);
pthread_cleanup_push()
は、routineに指定されたキャンセルハンドラを、呼び出したスレッドのキャンセルスタックに積みます。argは、キャンセルハンドラが呼び出される時に用いる引数を指定します。
キャンセルスタックからキャンセルハンドラが降ろされて実行されるのは、以下に示す場合の時です。
pthread_cleanup_pop()
が、0以外の引数を伴って呼ばれた場合。pthread_cleanup_push()
とpthread_cleanup_pop()
は、実装によってはマクロで実装されている物もあります。マクロが展開される時、2つのマクロは同一のスコープの中に展開されます。つまり、pthread_cleanup_push()
のマクロが展開される時の最初のトークンは'{
'で、pthread_cleanup_pop()
のマクロが展開される時の最後のトークンは'}
'になると考えて差し支えありません。
setjmp()
でジャンプ前の環境を保存した後、pthread_cleanup_push()
とpthread_cleanup_pop()
の呼び出し回数が一致しない状態でlongjmp()
やsiglongjmp()
を呼び出したの動作は未定義です。また、キャンセルハンドラの内部でsetjmp()
でジャンプ前の環境を保存した場合以外、キャンセルハンドラの内部からlongjmp()
やsiglongjmp()
を呼び出した時の動作は未定義です。
返り値がvoid
型なので、返り値はありません。
pthread_cleanup_push()
はエラーを起こしません。また、pthread_cleanup_push()
は、エラーコード[EINTR]で返る事はありません。
void pthread_cleanup_pop(int execute);
pthread_cleanup_pop()
は、呼び出したスレッドのキャンセルスタックの一番上からキャンセルハンドラを取り出します。executeが0以外の時は、取り出したキャンセルハンドラを実行します。
pthread_cleanup_push()
とpthread_cleanup_pop()
は、実装によってはマクロで実装されている物もあります。マクロが展開される時、2つのマクロは同一のスコープの中に展開されます。つまり、pthread_cleanup_push()
のマクロが展開される時の最初のトークンは'{
'で、pthread_cleanup_pop()
のマクロが展開される時の最後のトークンは'}
'になると考えて差し支えありません。
setjmp()
でジャンプ前の環境を保存した後、pthread_cleanup_push()
とpthread_cleanup_pop()
の呼び出し回数が一致しない状態でlongjmp()
やsiglongjmp()
を呼び出したの動作は未定義です。また、キャンセルハンドラの内部でsetjmp()
でジャンプ前の環境を保存した場合以外、キャンセルハンドラの内部からlongjmp()
やsiglongjmp()
を呼び出した時の動作は未定義です。
返り値がvoid
型なので、返り値はありません。
pthread_cleanup_pop()
はエラーを起こしません。また、pthread_cleanup_pop()
は、エラーコード[EINTR]で返る事はありません。
pthread_key_create()
スレッド固有データのキーを作成します。
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
pthread_key_create()
は、スレッド固有データのキーを作成します。このキーは、プロセス中の全てのスレッドで共有されます。pthread_key_create()
で作成したキーには、pthread_setspecific()
を用いてスレッド固有データを結びつける事が出来ます。キーを作成した時には、そのキーはプロセス中の全てのスレッドで共有されましたが、スレッド固有データはスレッド毎に独立しています。
以上をまとめると、
となります。
新しいキーを作った時、全てのスレッドのそのキーに対するスレッド固有データはNULLで初期化されます。新しいスレッドを作成した時、そのスレッドの全てのキーのスレッド固有データは、NULLで初期化されます。
destructorに、キー値key毎のデストラクタを指定できます。デストラクタが呼び出される時、引数としてキーに関連づけられているスレッド固有データが渡されます。必要が無い時はNULLを指定します。デストラクタは、destructorがNULLで無く、またスレッド固有データがNULLで無い時に実行されます。一つのスレッドが複数のスレッド固有データとそれに関連づけられたデストラクタを持っていて、スレッドが終了した時、デストラクタの実行の順序は特に定められていません。
NULLで無いスレッド固有データに対してデストラクタが全て実行された後に、まだNULLで無いスレッド固有データが残っている場合、再度デストラクタが呼び出されます。PTHREAD_DESTRUCTOR_ITERATIONS
で指定された回数繰り返してもNULLで無いスレッド固有データが存在する場合、実装によって以下のようになります。
後者の実装の場合、言うまでもなく無限ループに入る可能性があります。
pthread_key_create()
が成功した時には0を返します。他の場合は、以下に示す通りのエラーに応じた値を返します。
pthread_key_delete()
スレッド固有データのキーを削除します。
int pthread_key_delete(pthread_key_t key);
pthread_key_delete()
は、keyで指定されたキーを削除します。キーにデストラクタが関連づけられていても、デストラクタは呼び出されません。keyは、pthread_key_create()
によって得た値でなければなりません。pthread_key_delete()
は、keyに関連づけられたスレッド固有データは解放されません。スレッド固有データは、アプリケーションが解放する必要があります。スレッド固有データの解放は、pthread_key_delete()
でキーを削除する前でも後でも構いません。
pthread_key_delete()
で削除されたキーに対して、なんらかの操作を行う事の結果は未定義です。
pthread_key_delete()
はkeyに関連づけられているデストラクタを呼び出さないので、デストラクタの中から呼び出す事が可能です。pthread_key_delete()
で削除されたキーに関連づけられたデストラクタは、スレッドの終了の際ですら呼ばれる事はありません。
pthread_key_delete()
が成功した時には0を返します。他の場合は、以下に示す通りのエラーに応じた値を返します。
keyの値が無効です。
pthread_setspecific()
スレッド固有データをキーに関連づけます。
int pthread_setspecific(pthread_key_t key, const void *value);
pthread_setspecific()
は、keyで指定されたキーに、スレッド固有データへのポインタvalueを関連づけます。1つのキーに対して、スレッド毎に個別のスレッド固有データを関連づけられます。スレッド固有データは、一般的に呼び出し元のスレッドが動的に割り当てたメモリを用います。
pthread_key_create()
で作成されたキーをkeyに与えなかった時の動作は未定義です。pthread_key_delete()
で削除されたキーを用いた時の動作は未定義です。
pthread_setspecific()
は、デストラクタの中から呼び出す事が可能です。但し、デストラクタのコード次第では無限ループに陥る可能性があります。
pthread_setspecific()
が成功した時には0を返します。他の場合は、以下に示す通りのエラーに応じた値を返します。
pthread_getspecific()
キーに関連づけられたスレッド固有データを取得します。
void *pthread_getspecific(pthread_key_t key);
pthread_getspecific()
は、keyで指定されたキーに関連づけられたスレッド固有データを返します。pthread_setspecific()
によってキーにスレッド固有データが関連づけられていない時は、NULLが返ります。
pthread_key_create()
で作成されたキーをkeyに与えなかった時の動作は未定義です。pthread_key_delete()
で削除されたキーを用いた時の動作は未定義です。
pthread_getspecific()
は、デストラクタの中から呼び出す事が可能です。
pthread_getspecific()
はエラーを起こしません。また、pthread_getspecific()
は、エラーコード[EINTR]で返る事はありません。
pthread_cancel()
int pthread_cancel(pthread_t thread);
pthread_cancel()
は、threadで指定したスレッドをキャンセルします。キャンセルの動作は、キャンセル状態とキャンセルタイプによって決定されます。
スレッドがキャンセルすると、まずキャンセルハンドラが実行されます。全てのキャンセルハンドラの実行が終了すると、次にスレッド固有データのデストラクタが実行されます。全てのデストラクタの実行が終了すると、キャンセルされたスレッドは終了します。
pthread_cancel()
が成功した時には0を返します。他の場合は、以下に示す通りのエラーに応じた値を返します。
pthread_testcancel()
キャンセルポイントを作成します。
void pthread_testcancel(void);
返り値がvoid
型なので、返り値はありません。
pthread_testcancel()
はエラーを起こしません。また、pthread_testcancel()
は、エラーコード[EINTR]で返る事はありません。
pthread_setcancelstate()
キャンセル状態の設定をします。
int pthread_setcancelstate(int state, int *oldstate);
pthread_setcancelstate()
は、呼び出したスレッドのキャンセル状態をstateに設定し、同時にoldstateに以前のキャンセル状態をセットします。stateに指定出来る値はPTHREAD_CANCEL_ENABLEかPTHREAD_CANCEL_DISABLEです。
デフォルトのキャンセル状態はPTHREAD_CANCEL_ENABLEです。
pthread_setcancelstate()
が成功した時には0を返します。他の場合は、以下に示す通りのエラーに応じた値を返します。
以下のエラーは、実装によっては起こる事があります。
stateがPTHREAD_CANCEL_ENABLEかPTHREAD_CANCEL_DISABLEではありません。
エラーコード[EINTR]で返る事はありません。
pthread_setcanceltype()
キャンセルタイプの設定をします。
int pthread_setcanceltype(int type, int *oldtype);
pthread_setcanceltype()
は、呼び出したスレッドのキャンセルタイプをtypeに設定し、同時にoldtypeに以前のキャンセルタイプをセットします。stateに指定出来る値はPTHREAD_CANCEL_DEFEREDかPTHREAD_CANCEL_ASYNCHRONOUSです。
デフォルトのキャンセルタイプはPTHREAD_CANCEL_DEFEREDです。
pthread_setcanceltype()
が成功した時には0を返します。他の場合は、以下に示す通りのエラーに応じた値を返します。
以下のエラーは、実装によっては起こる事があります。
typeがPTHREAD_CANCEL_DEFEREDかPTHREAD_CANCEL_ASYNCHRONOUSではありません。
エラーコード[EINTR]で返る事はありません。