.\" Copyright (C) 1996-1999 Free Software Foundation, Inc. .\" .\" Permission is granted to make and distribute verbatim copies of .\" this manual provided the copyright notice and this permission notice are .\" preserved on all copies. .\" .\" Permission is granted to copy and distribute modified versions of .\" this manual under the conditions for verbatim copying, provided that .\" the entire resulting derived work is distributed under the terms of a .\" permission notice identical to this one. .\" .\" Permission is granted to copy and distribute translations of this .\" manual into another language, under the above conditions for modified .\" versions, except that this permission notice may be stated in a .\" translation approved by the Foundation. .\" .\" Copyright (C) 1996 Xavier Leroy. .\" .\" Japanese Version Copyright (C) 2002-2003 Suzuki Takashi .\" all rights reserved. .\" Translated Tue Dec 31 23:11:09 JST 2002 .\" by Suzuki Takashi. .\" .\"WORD: thread-specific data スレッド固有データ .\"WORD: thread-specific key スレッド固有キー .\"WORD: destructor function デストラクタ関数 .\" .\" .TH PTHREAD_SPECIFIC 3 LinuxThreads .SH "名前" pthread_key_create, pthread_key_delete, pthread_setspecific, pthread_getspecific \- スレッド固有データの管理 .SH "書式" .B #include .BI "int pthread_key_create(pthread_key_t *" key ", void (*" destr_function ") (void *));" .BI "int pthread_key_delete(pthread_key_t " key ");" .BI "int pthread_setspecific(pthread_key_t " key ", const void *" pointer ");" .BI "void * pthread_getspecific(pthread_key_t " key ");" .SH "説明" プログラムではスレッドごとに値の異なる グローバル変数や静的変数がしばしば必要となる。 複数のスレッドは 1 つのメモリ空間を共有するため、 通常の変数ではこれを実現することができない。 スレッド固有データは、 この必要性への POSIX スレッドの答えである。 それぞれのスレッドはスレッド固有データ (thread-specific data) 領域、 略して TSD 領域という プライベートなメモリブロックを保有している。 この領域は TSD キーをインデックスとして管理される。 TSD 領域では .B "void *" 型の値を TSD キーに結び付ける。 TSD キーはすべてのスレッドに共通であるが、 TSD キーに結び付けられる値はスレッドごとに異なるように することができる。 具体的にいえば、 TSD 領域は .B "void *" 型のポインタの配列として、 TSD キーはこの配列に対する整数値のインデックスとして、 TSD キーに結び付けられる値は呼び出しスレッドの対応する配列要素として見える。 スレッドが生成されると、TSD 領域はすべてのキーに対する値が .B "NULL" になるよう初期化される。 .B "pthread_key_create" は新しい TSD キーを確保する。 キーは .I "key" で指し示される領域に格納される。 ある時点で確保できるキーの数には制限があり、 その最大値は .B "PTHREAD_KEYS_MAX" である。 返されたキーに結び付けられる初期値は、 その時点で実行されているスレッドすべてにおいて .B "NULL" である。 引数 .I "destr_function" に .B "NULL" 以外の値を指定することで、 そのキーに対応するデストラクタ関数を登録することができる。 スレッドが .B "pthread_exit" やキャンセルによって終了すると、 そのスレッド中でキーに結び付けられた値を引数として関数 .I "destr_function" が呼び出される。 値が .B "NULL" の場合には関数 .I "destr_function" は呼び出されない。 スレッド終了時にデストラクタ関数が呼び出される順序は不定である。 デストラクタ関数が呼び出される前に、 現在のスレッドにおいてキーに結び付けられる値は .B "NULL" になる。 しかし、デストラクタ関数は .B "NULL" 以外の値をそのキーやほかのキーに結び付けるかもしれない。 これを処理するため、 すべての非 .B "NULL" の値に対するデストラクタ関数をすべて呼び出したあとに デストラクタ関数のある非 .B "NULL" の値がまだ残っている場合には、 デストラクタ関数の呼び出し処理は繰り返される。 LinuxThreads の実装では、 .B "PTHREAD_DESTRUCTOR_ITERATIONS" 回繰り返すと、たとえデストラクタ関数のある非 .B "NULL" の値が残っていても、 処理は中止される。LinuxThreads 以外の実装では無限ループに陥るかもしれない。 .B "pthread_key_delete" は TSD キーを解放する。 その時点で実行中のスレッドでキーに非 .B "NULL" の値が結び付けられているかどうかをチェックしたり、 キーに対応するデストラクタ関数を呼び出したりはしない。 .B "pthread_setspecific" は呼び出しスレッドで .I "key" に結び付けられる値を、与えられた .I "pointer" に変更する。 .B "pthread_getspecific" は呼び出しスレッドでその時点で .I "key" に結び付けられている値を返す。 .SH "返り値" .B "pthread_key_create" および .B "pthread_key_delete" 、 .B "pthread_setspecific" は成功すると 0 を、失敗すると非 0 のエラーコードを返す。 成功の場合、 .B "pthread_key_create" は新しく確保されたキーを 引数 .I "key" で指し示される領域に格納する。 .B "pthread_getspecific" は、成功するとキー .I "key" に結び付けられた値を、 エラーの場合には .B "NULL" を返す。 .SH "エラー" .B "pthread_key_create" はエラーの場合に次のようなエラーコードを返す: .RS .TP .B "EAGAIN" .B "PTHREAD_KEYS_MAX" だけのキーがすでに確保されている。 .RE .B "pthread_key_delete" および .B "pthread_setspecific" はエラーの場合に次のようなエラーコードを返す: .RS .TP .B "EINVAL" .I "key" は有効な、確保された TSD キーではない。 .RE .B "pthread_getspecific" は、 .I "key" が有効な、確保された TSD キーでない場合には .B "NULL" を返す。 .SH "著者" Xavier Leroy .SH "関連項目" pthread_create(3), pthread_exit(3), pthread_testcancel(3). .SH "例" 次のコードでは、100 バイトのスレッド固有の配列を確保し、 スレッドの終了とともに自動で解放する: .RS .ft 3 .nf .sp /* スレッド固有バッファのキー */ static pthread_key_t buffer_key; /* 1 回限りのキーの初期化 */ static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT; /* スレッド固有のバッファを確保する */ void buffer_alloc(void) { pthread_once(&buffer_key_once, buffer_key_alloc); pthread_setspecific(buffer_key, malloc(100)); } /* スレッド固有のバッファを返す */ char * get_buffer(void) { return (char *) pthread_getspecific(buffer_key); } /* キーを確保する */ static void buffer_key_alloc() { pthread_key_create(&buffer_key, buffer_destroy); } /* スレッド固有のバッファを解放する */ static void buffer_destroy(void * buf) { free(buf); } .ft .LP .RE .fi