理想未来ってなんやねん

娘可愛い。お父さん頑張る。

dispatch_async_f

Grand Central Dispatchの続き。
dispatch_async_fを使うと、ブロックの代わりに関数が使える。

こんな感じ。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#include <dispatch/dispatch.h>

typedef struct {
	int n;
	struct timeval basetime;
} my_param_t;

void print_function(void* context)
{
	pthread_t p = pthread_self();
	my_param_t* param = (my_param_t*)context;
	usleep(3000000);		
	
	struct timeval now;
	gettimeofday(&now, NULL);

	printf("time:%ld  thread:%p  param:%p  n:%d\n",
		   now.tv_sec - param->basetime.tv_sec, p, param, param->n);

	free(param);
}

int main (int argc, const char * argv[]) 
{
	dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
	dispatch_group_t group = dispatch_group_create();
	
	struct timeval  basetime;
	printf( "Loop start\n" );
	gettimeofday(&basetime, NULL);
	
	for(int i = 0; i < 1000; i++)
	{
		my_param_t* param = (my_param_t*)malloc(sizeof(my_param_t));
		param->n = i;
		param->basetime = basetime;
		
		dispatch_group_async_f(group, queue, param, print_function);
		usleep(10000);		
	}
	printf( "Loop end\n" );
	dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
	return 0;
}

上記の例ではdispatch_group_waitでタスクの終了を待つ為に、dispatch_async_fではなく、dispatch_group_async_fを使用している。
dispatch_group_async_fの第4引数が実行する関数で、第3引数が関数に渡すcontext。
ブロックと違い、ポインタ渡しになるので、値を書き換えるとタスクで読み取る値も変わってしまう。
その為、上記例ではmallocで確保したメモリに値を書いて渡している。
contextは毎回確保すると無駄なので、キューで管理し、足りなくなったら新規で確保し、使い終わったらキューに戻すようにした方が良いかもしれない。


Grand Central Dispatchの最新記事はこちら