pthread_key_create - ライブラリコールの説明 - Linux コマンド集 一覧表
名前
pthread_key_create, pthread_key_delete, pthread_setspecific, pthread_getspecific - スレッド固有データの管理
書式
#include <pthread.h>
int pthread_key_create(pthread_key_t *
key
, void (*
destr_function
) (void *));
int pthread_key_delete(pthread_key_t
key
);
int pthread_setspecific(pthread_key_t
key
, const void *
pointer
);
void * pthread_getspecific(pthread_key_t
key
);
説明
プログラムではスレッドごとに値の異なる
グローバル変数や静的変数がしばしば必要となる。
複数のスレッドは 1 つのメモリ空間を共有するため、
通常の変数ではこれを実現することができない。
スレッド固有データは、
この必要性への POSIX スレッドの答えである。
それぞれのスレッドはスレッド固有データ (thread-specific data) 領域、
略して TSD 領域という
プライベートなメモリブロックを保有している。
この領域は TSD キーをインデックスとして管理される。
TSD 領域では
"void *"
型の値を TSD キーに結び付ける。
TSD キーはすべてのスレッドに共通であるが、
TSD キーに結び付けられる値はスレッドごとに異なるように
することができる。
具体的にいえば、 TSD 領域は
"void *"
型のポインタの配列として、
TSD キーはこの配列に対する整数値のインデックスとして、
TSD キーに結び付けられる値は呼び出しスレッドの対応する配列要素として見える。
スレッドが生成されると、TSD 領域はすべてのキーに対する値が
"NULL"
になるよう初期化される。
"pthread_key_create"
は新しい TSD キーを確保する。
キーは
"key"
で指し示される領域に格納される。
ある時点で確保できるキーの数には制限があり、
その最大値は
"PTHREAD_KEYS_MAX"
である。
返されたキーに結び付けられる初期値は、
その時点で実行されているスレッドすべてにおいて
"NULL"
である。
引数
"destr_function"
に
"NULL"
以外の値を指定することで、
そのキーに対応するデストラクタ関数を登録することができる。
スレッドが
"pthread_exit"
やキャンセルによって終了すると、
そのスレッド中でキーに結び付けられた値を引数として関数
"destr_function"
が呼び出される。
値が
"NULL"
の場合には関数
"destr_function"
は呼び出されない。
スレッド終了時にデストラクタ関数が呼び出される順序は不定である。
デストラクタ関数が呼び出される前に、
現在のスレッドにおいてキーに結び付けられる値は
"NULL"
になる。
しかし、デストラクタ関数は
"NULL"
以外の値をそのキーやほかのキーに結び付けるかもしれない。
これを処理するため、
すべての非
"NULL"
の値に対するデストラクタ関数をすべて呼び出したあとに
デストラクタ関数のある非
"NULL"
の値がまだ残っている場合には、
デストラクタ関数の呼び出し処理は繰り返される。
LinuxThreads の実装では、
"PTHREAD_DESTRUCTOR_ITERATIONS"
回繰り返すと、たとえデストラクタ関数のある非
"NULL"
の値が残っていても、
処理は中止される。LinuxThreads 以外の実装では無限ループに陥るかもしれない。
"pthread_key_delete"
は TSD キーを解放する。
その時点で実行中のスレッドでキーに非
"NULL"
の値が結び付けられているかどうかをチェックしたり、
キーに対応するデストラクタ関数を呼び出したりはしない。
"pthread_setspecific"
は呼び出しスレッドで
"key"
に結び付けられる値を、与えられた
"pointer"
に変更する。
"pthread_getspecific"
は呼び出しスレッドでその時点で
"key"
に結び付けられている値を返す。
返り値
"pthread_key_create"
および
"pthread_key_delete"
、
"pthread_setspecific"
は成功すると 0 を、失敗すると非 0 のエラーコードを返す。
成功の場合、
"pthread_key_create"
は新しく確保されたキーを
引数
"key"
で指し示される領域に格納する。
"pthread_getspecific"
は、成功するとキー
"key"
に結び付けられた値を、
エラーの場合には
"NULL"
を返す。
エラー
"pthread_key_create"
はエラーの場合に次のようなエラーコードを返す:
- "EAGAIN"
-
"PTHREAD_KEYS_MAX"
だけのキーがすでに確保されている。
"pthread_key_delete" および "pthread_setspecific" はエラーの場合に次のようなエラーコードを返す:
- "EINVAL"
-
"key"
は有効な、確保された TSD キーではない。
"pthread_getspecific" は、 "key" が有効な、確保された TSD キーでない場合には "NULL" を返す。
著者
Xavier Leroy <Xavier.Leroy@inria.fr>
関連項目
pthread_create(3), pthread_exit(3), pthread_testcancel(3).
例
次のコードでは、100 バイトのスレッド固有の配列を確保し、
スレッドの終了とともに自動で解放する:
/* スレッド固有バッファのキー */ 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); }