Your SlideShare is downloading. ×
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Boost.Coroutine
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Boost.Coroutine

10,216

Published on

0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
10,216
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
20
Comments
0
Likes
8
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Boost.Coroutine
  • 2. 自己紹介 ・めるぽん ・SICP(計算機プログラムの構造と解釈)未読 ・CTMCP(コンピュータプログラミングの概念・技法・モデル)未読 ・D&E未読 ・英語本未読
  • 3. アジェンダ ・Boost.Coroutine とは ・Boost.Coroutine の入手方法 ・Boost.Coroutine の使い方 ・Boost.Coroutine の実装 ・Boost.Coroutine の未来 ・Boost.Coroutine のまとめ
  • 4. Boost.Coroutine とは ・関数の実行を途中で凍結・再実行させる機構 int f(coroutine<int ()>::self& self) { int n = 0; while (true) ++n, self.yield(n * n); self.exit(); } int main() { coroutine<int ()> coro(f); std::cout << coro() << std::endl; // 1 * 1 = 1 std::cout << coro() << std::endl; // 2 * 2 = 4 std::cout << coro() << std::endl; // 3 * 3 = 9 }
  • 5. Boost.Coroutine とは ・別名: micro-thread, fiber, continuation ・スレッドによく似ている ・コンテキストの切り替えはシステムではなくユーザが手動で行う ・同期が取りやすい ・使い方はいろいろ ・視点を変えると別の意味になったりする ・Boost ライブラリに正式に採用されていない
  • 6. Boost.Coroutine の入手方法 ・Boost.Vault から持ってくる
  • 7. Boost.Coroutine の入手方法 ・Boost.Vault から持ってくる
  • 8. Boost.Coroutine の入手方法 ・Boost.Vault から持ってくる
  • 9. Boost.Coroutine の入手方法 ・Boost.Vault から持ってくる
  • 10. Boost.Coroutine の使い方 using namespace boost::coroutines; typedef coroutine<int ()> coro_type; int f(coro_type::self& self) { int n = 0; while (true) ++n, self.yield(n * n); self.exit(); } int main() { coro_type std::cout std::cout std::cout } coro(f); << coro() << std::endl; // 1 * 1 = 1 << coro() << std::endl; // 2 * 2 = 4 << coro() << std::endl; // 3 * 3 = 9
  • 11. Boost.Coroutine の使い方 using namespace boost::coroutines; typedef generator<int> gen_type; int f(gen_type::self& self) { int n = 0; while (true) ++n, self.yield(n * n); self.exit(); } int main() { gen_type gen(f); while (gen != generator_type()) { *gen; // 1, 4, 9, 16, ... ++gen; } }
  • 12. Boost.Coroutine の使い方 void bullet(point pt) for (int i = 0; i for (int i = 0; i for (int i = 0; i } { < 10; i++) ++pt.x; < 20; i++) ++pt.y; < 30; i++) --pt.x; ・こんな弾の動きを作りたい。けど、 void bullet(int& state, point& pt) { if (0 <= state && state < 10) ++pt.x; if (10 <= state && state < 30) ++pt.y; if (30 <= state && state < 60) --pt.x; ++state; } ・こんな非直感的なコードを書かないといけない
  • 13. Boost.Coroutine の使い方 point bullet(coro_type::self& self, point pt) { for (int i = 0; i < 10; i++) ++pt.x, self.yield(pt); for (int i = 0; i < 20; i++) ++pt.y, self.yield(pt); for (int i = 0; i < 30; i++) --pt.x, self.yield(pt); self.exit(); } class bullet_task { coro_type coro_; public: bullet_task() : coro_(boost::bind(bullet, _1, point(10, 20)){} bool move() { point pt = coro_(std::nothrow); return coro_; } };
  • 14. Boost.Coroutine の使い方 BOOL EnumWindows( WNDENUMPROC lpEnumFunc, // コールバック関数 LPARAM lParam // アプリケーション定義の値 ); ・コールバックでウインドウを列挙する関数 BOOL CALLBACK callback(HWND hwnd, LPARAM param) { // hwnd を使ってごにょごにょする } int main() { ::EnumWindows(callback, param); } ・すごく使いにくい ・イテレータみたいな使い方がしたい
  • 15. Boost.Coroutine の使い方 typedef generator<HWND> gen_type; BOOL CALLBACK callback(HWND hwnd, LPARAM param) { gen_type::self& self = *reinterpret_cast<gen_type::self*>(param); self.yield(hwnd); return TRUE; } HWND enum_windows(gen_type::self& self) { ::EnumWindows(&callback, reinterpret_cast<LPARAM>(&self)); self.exit(); } int main() { gen_type it(enum_windows); while (it != gen_type()) { std::cout << (void*)*it << std::endl; ++it; } }
  • 16. Boost.Coroutine の実装 ・Windows の場合 ・Fiber を使う ・Mac(POSIX) の場合 ・ucontext を使う ・Linux の場合 ・アセンブラを使う
  • 17. Boost.Coroutine の実装 ・環境によってはコンテキストを自由に作れない ・セキュリティ的に問題あり ・だからこそのFiberやucontext ・組み込み環境で特に有効 ・スレッドも使えない上に何ms以内にシステムに返せとか面倒 ・アセンブラで自作できる場合が多い ・BREW 環境上(ARM アセンブラ)で作ってみて無事動いた ・実装を知っておくと好きな環境で作れる
  • 18. Boost.Coroutine の実装 ・コンテキストとは ・実行するために必要なもの void f(coro_type::self& self) { int a; // a, b はスタックに置かれている int b; // a, b は yield されても保持されている self.yield(); } ・スタック ・レジスタ ・(例外情報) ・これらを保存して実行中のコンテキストを切り替える
  • 19. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える
  • 20. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2
  • 21. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Main SP→
  • 22. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Main SP→ coro Coroutine
  • 23. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Main Coroutine 0 SP→ coro &f
  • 24. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Main Coroutine 0 SP→ coro &f
  • 25. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Main SP→ Coroutine r0 pc2 0 coro &f
  • 26. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Coroutine Main r0 pc2 coro SP→ 0 &f
  • 27. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Coroutine Main r0 pc2 coro SP→
  • 28. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Coroutine Main r0 pc2 coro SP→
  • 29. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Coroutine Main r0 pc2 coro SP→ a
  • 30. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Coroutine Main r0 pc2 coro SP→ a
  • 31. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Coroutine Main r0 SP→ r0 pc2 pc1 coro a
  • 32. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Main SP→ Coroutine r0 r0 pc2 pc1 coro a
  • 33. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Main Coroutine r0 pc1 SP→ coro a
  • 34. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える void f(coro_type::self& self) { int a; self.yield(); // pc1 } coro_type coro(f); coro(); // pc2 Main Coroutine r0 pc1 SP→ coro a
  • 35. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える pushl %ebp pushl %ebx pushl %esi pushl %edi movl %esp, (%eax) movl %edx, %esp popl %edi popl %esi popl %ebx popl %ebp ret PUSH {r0-r12,lr} STR sp,[r0] MOV sp,r1 POP {r0-r12,lr} MOV pc,lr
  • 36. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える pushl %ebp pushl %ebx pushl %esi pushl %edi movl %esp, (%eax) movl %edx, %esp popl %edi popl %esi popl %ebx popl %ebp ret PUSH {r0-r12,lr} STR sp,[r0] MOV sp,r1 POP {r0-r12,lr} MOV pc,lr
  • 37. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える pushl %ebp pushl %ebx pushl %esi pushl %edi movl %esp, (%eax) movl %edx, %esp popl %edi popl %esi popl %ebx popl %ebp ret PUSH {r0-r12,lr} STR sp,[r0] MOV sp,r1 POP {r0-r12,lr} MOV pc,lr
  • 38. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える pushl %ebp pushl %ebx pushl %esi pushl %edi movl %esp, (%eax) movl %edx, %esp popl %edi popl %esi popl %ebx popl %ebp ret PUSH {r0-r12,lr} STR sp,[r0] MOV sp,r1 POP {r0-r12,lr} MOV pc,lr
  • 39. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える pushl %ebp pushl %ebx pushl %esi pushl %edi movl %esp, (%eax) movl %edx, %esp popl %edi popl %esi popl %ebx popl %ebp ret PUSH {r0-r12,lr} STR sp,[r0] MOV sp,r1 POP {r0-r12,lr} MOV pc,lr
  • 40. Boost.Coroutine の実装 ・他の方法で実装するのもあり ・機械的に状態マシンに置き換える(C#) IEnumerable<int> GetEnumerator() { yield return 2; yield return 4; } int state, result; int GetCurrent() { bool MoveNext() { switch (state) case 0: result case 1: result case 2: return } } result; } { = 2; state = 1; return true; = 4; state = 2; return true; false;
  • 41. Boost.Coroutine の実装 ・他の方法で実装するのもあり ・スレッドを使って実装する ・アセンブラが直接弄れないけど Coroutine が使いたい!(Java とか) public final class Coro implements CoroutineFunction { public void coro(Coroutine.Self self) { self.yield(); self.yield(); } } Coroutine c = new Coroutine(new Coro()); c.coro();
  • 42. Boost.Coroutine の未来 ・Boost.ML を追いかけた ・2008/7/26 に sandbox 上の Boost.Coroutine を更新している ・複雑になりすぎたのでもっと単純なインターフェースにするとか何とか ・作者は ML には結構出てきてるのでちゃんと元気にしてるっぽい ・やる気が無い? ・作者以外の人が頑張っている ・Mac 版の対応 ・バグの修正 ・Boost.Coroutine の未来 ・正式に採用されるのかどうか分からない ・Boost.Fiber という対抗馬も最近出てきた
  • 43. Boost.Coroutine のまとめ ・手動マルチスレッド ・いろいろな使い方ができる ・実装はスタックポインタの書き換え ・それ以外の方法で実装するのもあり ・Boost.Coroutine は実装の模範例 ・利用は自己責任
  • 44. おわり

×