Blocks+gcd入門
Upcoming SlideShare
Loading in...5
×
 

Blocks+gcd入門

on

  • 4,292 views

BlocksとGrand Central Dispatchの紹介です。

BlocksとGrand Central Dispatchの紹介です。

Statistics

Views

Total Views
4,292
Views on SlideShare
4,285
Embed Views
7

Actions

Likes
6
Downloads
21
Comments
0

2 Embeds 7

https://twitter.com 4
http://paper.li 3

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • C標準ワーキンググループに提案されています。\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • コンパイル環境\nclang は C系言語 をターゲットとしたコンパイラで、LLVM 上で動作\n詳しくはWikipediaで。\n
  • \n
  • \n
  • \n
  • これでHello worldが出力されます。ハット記号・波括弧・括弧。これは省略形。\n
  • 引数・戻り値を表記して、変数に代入するとこうなります。\n
  • 引数・戻り値を表記して、変数に代入するとこうなります。\n
  • 引数・戻り値を表記して、変数に代入するとこうなります。\n
  • 最初のHello worldは詳細に記述すると上になります。\n
  • iをキャプチャしてます。iを変更してもblockにキャプチャされた変数は変更されてません。ちなみにC言語の配列はそのままではblockはキャプチャできません。なのでポインタを使用してキャプチャします。\n
  • __block指定子を付けることでblock内で変数の値を変更することが出来ます。\n
  • __block指定子を付けることでblock内で変数の値を変更することが出来ます。\n
  • __block指定子を付けることでblock内で変数の値を変更することが出来ます。\n
  • __blockが付くと、元のiを変更するとblockでも変更された変数が利用されます。\n
  • blockを再帰呼び出しする場合はblockに__block指定子を付けます\n
  • blockを再帰呼び出しする場合はblockに__block指定子を付けます\n
  • blockを返すblockを定義しています。デフォルトではスタックに確保されるので、スコープから出たら開放されてしまいます。ので、Block_copyでヒープにコピーします。ヒープにコピーしたものはBlock_releaseで開放します。Objective-CだとBlockをオブジェクトとして利用できるので、ちょっと扱いが違ってきます。\n
  • 分かりにくい宣言はtypedefで分かりやすく\n
  • ということで、カウンターを作ってみるとこんなふうになります。\nBlocksを使うことでコーディングが一変します。ぜひ使ってみてください。\n
  • \n
  • ライセンスはApache 2.0です。FreeBSDにもポーティングされました。\n
  • タスクを非同期に実行する技術\n
  • \n
  • \n
  • キューに入れたタスクがどうなるか。\nプログラマがスレッドを用意したりキューとタスクを管理したりする必要が有りません。\nシステムレベルで管理することで、CPUのコア数に合わせてスレッドが作成されます。なので、効率良く実行されます。\nGCDは空いたスレッドを自動的に再利用します。\n
  • Mac OS XやFreeBSDではカーネルレベルで実装されていますが、Debian/Ubuntuではそうではないようです。\n
  • \n
  • \n
  • \n
  • Serialは順次、Concurrentは同時発生という意味\n
  • \n
  • \n
  • 高優先度、 標準優先度、低優先度、バックグラウンド優先度の4つの優先度があります。ただし、GCDはリアルタイムというわけではないので目安に過ぎません。\n\n
  • dispatch_retainやdispatch_releaseをMainキューやグローバルキューに行っても、何も起きません。\ndispatch_set_target_queueでDispatch Queueの実行階層を作ることも可能です。\n
  • \n
  • \n
  • \n
  • デッドロックに注意が必要です。たとえばメインスレッドからメインスレッドキューにdispatch_syncでブロックを登録すると、デッドロックになります。\n
  • カレントスレッドは停止され、グループ化されたタスクの実行が終了するのを待ちます。待ち時間はdispatch_group_waitのdispatch_time_t型の二つ目の引数で指定します。DISPATCH_TIME_FOREVERで永遠に待ちますが、時間を指定することが出来ます。\ndispatch_group_waitは戻り値があって、0ですべての処理が完了、0以外だとまだ実行中を表します。DISPATCH_TIME_NOWを渡すと、すぐに実行状態を調べられます。\n
  • この場合、終了を待ちません。\n
  • リアルタイム性はないので、3秒くらい後にキューに追加され、他にタスクが登録されていれば、実行されるタイミングはさらに遅くなると考えてください。\n
  • dispatch_barrier_syncという関数もあります。\n
  • それぞれのタスクは並列に実行されますが、すべての処理が終了するまで待ちます。\n
  • \n
  • キューのsuspendとresumeを行えます。\nDispatch I/Oで複数のスレッドを使って並列に読み込む。\nセマフォで排他制御。\nDispatch Sourceはkqueueのラッパー。\n
  • \n
  • \n
  • \n

Blocks+gcd入門 Blocks+gcd入門 Presentation Transcript

  • #include <stdio.h>#include <Block.h>int main (int argc, const char * argv[]) { void (^add)(int, int) = ^(int i, int j) { printf("%d", i + j); }; return 0;}
  • ^{ printf("Hello world!n");}();
  • int (^add)(int, int) = ^int(int i, int j) { return i + j;};printf("%dn", add(1, 1)); // 2
  • int (^add)(int, int) = ^int(int i, int j) { return i + j;};printf("%dn", add(1, 1)); // 2
  • int (^add)(int, int) = ^int(int i, int j) { return i + j;};printf("%dn", add(1, 1)); // 2
  • int (^add)(int, int) = ^int(int i, int j) { return i + j;};printf("%dn", add(1, 1)); // 2
  • ^void(void) { printf("Hello world!n");}();^{ printf("Hello world!n");}();
  • int i = 100;int (^add)(int) = ^(int j) { return i + j;};printf("%d", add(1)); // 101i = 200;printf("%d", add(1)); // 101
  • __block int i = 0;int (^f)(int) = ^(int j) { i++; return i + j;};for (int index = 0; index < 10; index++) { printf("%d ", f(index));} // 1 3 5 7 9 11 13 15 17 19
  • __block int i = 0;int (^f)(int) = ^(int j) { i++; return i + j;};for (int index = 0; index < 10; index++) { printf("%d ", f(index));} // 1 3 5 7 9 11 13 15 17 19
  • __block int i = 0;int (^f)(int) = ^(int j) { i++; return i + j;};for (int index = 0; index < 10; index++) { printf("%d ", f(index));} // 1 3 5 7 9 11 13 15 17 19
  • __block int i = 0;int (^f)(int) = ^(int j) { i++; return i + j;};for (int index = 0; index < 10; index++) { printf("%d ", f(index));} // 1 3 5 7 9 11 13 15 17 19
  • __block int i = 100;int (^add)(int) = ^(int j) { return i + j;};printf("%d", add(1)); // 101i = 200;printf("%d", add(1)); // 201
  • __block void (^reverse)(int, int) = ^(int curt, intmax) { if (curt < max) { reverse(curt + 1, max); } printf("%d ", curt);};reverse(0, 10); // 10 9 8 7 6 5 4 3 2 1 0
  • __block void (^reverse)(int, int) = ^(int curt, intmax) { if (curt < max) { reverse(curt + 1, max); } printf("%d ", curt);};reverse(0, 10); // 10 9 8 7 6 5 4 3 2 1 0
  • __block void (^reverse)(int, int) = ^(int curt, intmax) { if (curt < max) { reverse(curt + 1, max); } printf("%d ", curt);};reverse(0, 10); // 10 9 8 7 6 5 4 3 2 1 0
  • int (^(^curried_add)(int))(int) = ^(int x) { return Block_copy(^(int y) { return x + y; });};int (^add)(int) = curried_add(1);printf("%dn", add(1)); // 2Block_release(add);
  • int (^(^curried_add)(int))(int)... typedef int (^IntBlock)(int); IntBlock (^curried_add)(int)...
  • typedef int (^Block)(void);Block counter() { __block int i = 0; return Block_copy(^{ i += 1; return i; });}int main (int argc, const char * argv[]){ Block c = counter(); printf("%dn", c()); // 1 printf("%dn", c()); // 2 printf("%dn", c()); // 3 Block_release(c); return 0;}
  • #include <stdio.h>#include <dispatch/dispatch.h>int main (int argc, const char * argv[]){ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ sleep(1); printf("Hello world!n"); }); sleep(3); return 0;}
  • #include <stdio.h>#include <dispatch/dispatch.h>int main (int argc, const char * argv[]){ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ sleep(1); printf("Hello world!n"); }); sleep(3); return 0;}
  • dispatch_queue_t mq = dispatch_get_main_queue();dispatch_queue_t gqd = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_queue_t gqh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);dispatch_queue_t gql = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);dispatch_queue_t gqb = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);dispatch_queue_t cq = dispatch_queue_create("com.example.ConcurrentDispatchQueue",DISPATCH_QUEUE_CONCURRENT);dispatch_release(cq);dispatch_queue_t sq = dispatch_queue_create("com.example.SerialDispatchQueue", DISPATCH_QUEUE_SERIAL);dispatch_release(sq);
  • dispatch_async(queue,^{ hoge();});
  • dispatch_sync(queue, ^{ hoge();});
  • dispatch_group_t group = dispatch_group_create();dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_group_async(group, queue, ^{ hoge();});dispatch_group_async(group, queue, ^{ piyo();});dispatch_group_wait(group, DISPATCH_TIME_FOREVER);dispatch_release(group);
  • dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_group_t group = dispatch_group_create();dispatch_group_async(group, queue, ^{hoge(1);});dispatch_group_async(group, queue, ^{hoge(2);});dispatch_group_notify(group, dispatch_get_main_queue(), ^{printf("done");});dispatch_release(group);
  • dispatch_time_t time =dispatch_time(DISPATCH_TIME_NOW, 3.0 *NSEC_PER_SEC);dispatch_after(time, queue, ^{ hoge();});
  • dispatch_queue_t queue =dispatch_queue_create("com.example.ConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);dispatch_async(queue, ^{ 1});dispatch_barrier_async(queue, ^{ hoge();});dispatch_async(queue, ^{ 3});
  • dispatch_apply(10, queue, ^(size_t index) { hoge(index);});
  • static dispatch_once_t pred;dispatch_once(&pred, ^{ hoge();});
  • dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);for (int i = 0; i < 1000; i++) { dispatch_async(queue, ^{ hoge(i); dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); piyo(); dispatch_semaphore_signal(semaphore); });}dispatch_release(semaphore);