「pthread スレッドに値を渡す方法」の版間の差分

提供: C言語入門
移動: 案内検索
(ソースコード pthread_create1.c)
 
行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) {
                 err(EXIT_FAILURE, "can not join thread 1");
+
                 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) {
                 err(EXIT_FAILURE, "can not join thread 2");
+
                 errc(EXIT_FAILURE, ret2, "can not join thread 2");
 
         }
 
         }
  
行98: 行99:
 
         printf("arg2 = %d\n", arg2);
 
         printf("arg2 = %d\n", arg2);
  
         return EXIT_SUCCESS;
+
         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

関連項目