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は毎回確保すると無駄なので、キューで管理し、足りなくなったら新規で確保し、使い終わったらキューに戻すようにした方が良いかもしれない。