「pthread スレッドに値を渡す方法」の版間の差分
提供: C言語入門
(ページの作成:「pthreadのスレッドに引数を与えるには、pthread_createの第4引数にポインタを渡すことで実現します。1つのポインタしか渡せな...」) |
(→ソースコード pthread_create1.c) |
||
(同じ利用者による、間の1版が非表示) | |||
行13: | 行13: | ||
スレッドとして動作する関数ポインタは、第3引数の | スレッドとして動作する関数ポインタは、第3引数の | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
− | + | void *(*start_routine)(void *) | |
</syntaxhighlight> | </syntaxhighlight> | ||
です。 | です。 | ||
行64: | 行64: | ||
#include <stdlib.h> | #include <stdlib.h> | ||
#include <err.h> | #include <err.h> | ||
+ | #include <string.h> | ||
#include <pthread.h> | #include <pthread.h> | ||
#include <unistd.h> | #include <unistd.h> | ||
行79: | 行80: | ||
if (ret1 != 0) { | if (ret1 != 0) { | ||
− | err(EXIT_FAILURE, "can not create thread 1"); | + | err(EXIT_FAILURE, "can not create thread 1: %s", strerror(ret1) ); |
} | } | ||
if (ret2 != 0) { | if (ret2 != 0) { | ||
− | err(EXIT_FAILURE, "can not create thread 2"); | + | err(EXIT_FAILURE, "can not create thread 2: %s", strerror(ret2) ); |
} | } | ||
ret1 = pthread_join(thread1,NULL); | ret1 = pthread_join(thread1,NULL); | ||
if (ret1 != 0) { | if (ret1 != 0) { | ||
− | + | errc(EXIT_FAILURE, ret1, "can not join thread 1"); | |
} | } | ||
ret2 = pthread_join(thread2,NULL); | ret2 = pthread_join(thread2,NULL); | ||
if (ret2 != 0) { | if (ret2 != 0) { | ||
− | + | errc(EXIT_FAILURE, ret2, "can not join thread 2"); | |
} | } | ||
行98: | 行99: | ||
printf("arg2 = %d\n", arg2); | printf("arg2 = %d\n", arg2); | ||
− | + | exit(EXIT_SUCCESS); | |
} | } | ||
行119: | 行120: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
=== コンパイル === | === コンパイル === | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> |
2014年5月11日 (日) 16:04時点における最新版
pthreadのスレッドに引数を与えるには、pthread_createの第4引数にポインタを渡すことで実現します。1つのポインタしか渡せないので、複数のデータを渡したい場合は、構造体にまとめ、構造体のポインタを渡します。スレッドへ値を渡す以外に、スレッドから値を返す入れ物としても利用できます。
概要
pthread_createのプロトタイプは、以下の通りです。
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
スレッドとして動作する関数ポインタは、第3引数の
void *(*start_routine)(void *)
です。
スレッドの引数に渡るのは、第4引数の
void *arg
です。
整数を渡す場合は、以下のように書きます。
int x = 1234; pthread_t th; int ret = pthread_create(&th, NULL, func, (void*)&x); pthread_join(th, NULL);
複数のデータを渡したい場合は、構造体にまとめるなどします。
struct foo { int x; int y; int z; }; void bar() { struct foo x; x.x = 1; x.y = 2; x.z = 3; pthread_t th; int ret = pthread_create(&th, NULL, func, (void*)&x); pthread_join(th, NULL); }
pthread_createを呼び出す時に、自動変数のポインタを渡した場合、その関数内で pthread_join できないのであれば、自動変数ではなく、動的にメモリを確保して、渡すべきです。しかし、動的に確保したメモリをfreeすることに注意を払う必要が出てきます。
pthread_create1.c の例
このコードは、スレッドで渡された値を2倍にするだけのコードです。 この例では、自動変数へのポインタをスレッドに渡していますが、スレッドが終了するまで、自動変数が存在することを保証できるコードであるため、問題はありません。自動変数の存在が保証されるというのは、main()関数のスコープ内で、pthread_join()しているからです。
ソースコード pthread_create1.c
#include <stdio.h> #include <stdlib.h> #include <err.h> #include <string.h> #include <pthread.h> #include <unistd.h> void* f1(void *p); void* f2(void *p); int main(int argc, char *argv[]) { pthread_t thread1, thread2; int arg1 = 123, arg2 = 456; int ret1,ret2; ret1 = pthread_create(&thread1,NULL,(void *)f1,(void *) & arg1); ret2 = pthread_create(&thread2,NULL,(void *)f2,(void *) & arg2); if (ret1 != 0) { err(EXIT_FAILURE, "can not create thread 1: %s", strerror(ret1) ); } if (ret2 != 0) { err(EXIT_FAILURE, "can not create thread 2: %s", strerror(ret2) ); } ret1 = pthread_join(thread1,NULL); if (ret1 != 0) { errc(EXIT_FAILURE, ret1, "can not join thread 1"); } ret2 = pthread_join(thread2,NULL); if (ret2 != 0) { errc(EXIT_FAILURE, ret2, "can not join thread 2"); } printf("arg1 = %d\n", arg1); printf("arg2 = %d\n", arg2); exit(EXIT_SUCCESS); } void* f1(void *p) { int *ip = (int *)p; printf("%s: %d\n", __func__, *ip); *ip *=2; pthread_exit(NULL); } void* f2(void *p) { int *ip = (int *)p; printf("%s: %d\n", __func__, *ip); *ip *=2; pthread_exit(NULL); }
コンパイル
cc -lpthread pthread_create1.c -o pthread_create1
実行例
% ./pthread_create1 f2: 456 f1: 123 arg1 = 246 arg2 = 912