Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Boost.Coroutine
自己紹介
・めるぽん
・SICP(計算機プログラムの構造と解釈)未読
・CTMCP(コンピュータプログラミングの概念・技法・モデル)未読
・D&E未読
・英語本未読
アジェンダ
・Boost.Coroutine とは
・Boost.Coroutine の入手方法
・Boost.Coroutine の使い方
・Boost.Coroutine の実装
・Boost.Coroutine の未来
・Boost.Co...
Boost.Coroutine とは
・関数の実行を途中で凍結・再実行させる機構
int f(coroutine<int ()>::self& self) {
int n = 0;
while (true) ++n, self.yield(n ...
Boost.Coroutine とは
・別名: micro-thread, fiber, continuation
・スレッドによく似ている
・コンテキストの切り替えはシステムではなくユーザが手動で行う
・同期が取りやすい

・使い方はいろいろ...
Boost.Coroutine の入手方法
・Boost.Vault から持ってくる
Boost.Coroutine の入手方法
・Boost.Vault から持ってくる
Boost.Coroutine の入手方法
・Boost.Vault から持ってくる
Boost.Coroutine の入手方法
・Boost.Vault から持ってくる
Boost.Coroutine の使い方
using namespace boost::coroutines;
typedef coroutine<int ()> coro_type;
int f(coro_type::self& self) ...
Boost.Coroutine の使い方
using namespace boost::coroutines;
typedef generator<int> gen_type;
int f(gen_type::self& self) {
int...
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;
<...
Boost.Coroutine の使い方
point bullet(coro_type::self& self, point pt) {
for (int i = 0; i < 10; i++) ++pt.x, self.yield(pt);
...
Boost.Coroutine の使い方
BOOL EnumWindows(
WNDENUMPROC lpEnumFunc, // コールバック関数
LPARAM lParam // アプリケーション定義の値
);

・コールバックでウインドウ...
Boost.Coroutine の使い方
typedef generator<HWND> gen_type;
BOOL CALLBACK callback(HWND hwnd, LPARAM param) {
gen_type::self& s...
Boost.Coroutine の実装
・Windows の場合
・Fiber を使う

・Mac(POSIX) の場合
・ucontext を使う

・Linux の場合
・アセンブラを使う
Boost.Coroutine の実装
・環境によってはコンテキストを自由に作れない
・セキュリティ的に問題あり
・だからこそのFiberやucontext

・組み込み環境で特に有効
・スレッドも使えない上に何ms以内にシステムに返せとか面倒...
Boost.Coroutine の実装
・コンテキストとは
・実行するために必要なもの
void f(coro_type::self& self) {
int a; // a, b はスタックに置かれている
int b; // a, b は y...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
void f(coro_type::self& sel...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
pushl %ebp
pushl %ebx
pushl...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
pushl %ebp
pushl %ebx
pushl...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
pushl %ebp
pushl %ebx
pushl...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
pushl %ebp
pushl %ebx
pushl...
Boost.Coroutine の実装
・コンテキストの切り替え方
1.必要な情報を保存する
2.スタックポインタを書き換える
3.必要な情報を読み込む
4.プログラムカウンタを書き換える
pushl %ebp
pushl %ebx
pushl...
Boost.Coroutine の実装
・他の方法で実装するのもあり
・機械的に状態マシンに置き換える(C#)
IEnumerable<int> GetEnumerator() {
yield return 2;
yield return 4;...
Boost.Coroutine の実装
・他の方法で実装するのもあり
・スレッドを使って実装する
・アセンブラが直接弄れないけど Coroutine が使いたい!(Java とか)
public final class Coro impleme...
Boost.Coroutine の未来
・Boost.ML を追いかけた
・2008/7/26 に sandbox 上の Boost.Coroutine を更新している
・複雑になりすぎたのでもっと単純なインターフェースにするとか何とか

・作...
Boost.Coroutine のまとめ
・手動マルチスレッド
・いろいろな使い方ができる
・実装はスタックポインタの書き換え
・それ以外の方法で実装するのもあり

・Boost.Coroutine は実装の模範例
・利用は自己責任
おわり
Upcoming SlideShare
Loading in …5
×

Boost.Coroutine

24,974 views

Published on

  • Be the first to comment

Boost.Coroutine

  1. 1. Boost.Coroutine
  2. 2. 自己紹介 ・めるぽん ・SICP(計算機プログラムの構造と解釈)未読 ・CTMCP(コンピュータプログラミングの概念・技法・モデル)未読 ・D&E未読 ・英語本未読
  3. 3. アジェンダ ・Boost.Coroutine とは ・Boost.Coroutine の入手方法 ・Boost.Coroutine の使い方 ・Boost.Coroutine の実装 ・Boost.Coroutine の未来 ・Boost.Coroutine のまとめ
  4. 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. 5. Boost.Coroutine とは ・別名: micro-thread, fiber, continuation ・スレッドによく似ている ・コンテキストの切り替えはシステムではなくユーザが手動で行う ・同期が取りやすい ・使い方はいろいろ ・視点を変えると別の意味になったりする ・Boost ライブラリに正式に採用されていない
  6. 6. Boost.Coroutine の入手方法 ・Boost.Vault から持ってくる
  7. 7. Boost.Coroutine の入手方法 ・Boost.Vault から持ってくる
  8. 8. Boost.Coroutine の入手方法 ・Boost.Vault から持ってくる
  9. 9. Boost.Coroutine の入手方法 ・Boost.Vault から持ってくる
  10. 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. 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. 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. 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. 14. Boost.Coroutine の使い方 BOOL EnumWindows( WNDENUMPROC lpEnumFunc, // コールバック関数 LPARAM lParam // アプリケーション定義の値 ); ・コールバックでウインドウを列挙する関数 BOOL CALLBACK callback(HWND hwnd, LPARAM param) { // hwnd を使ってごにょごにょする } int main() { ::EnumWindows(callback, param); } ・すごく使いにくい ・イテレータみたいな使い方がしたい
  15. 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. 16. Boost.Coroutine の実装 ・Windows の場合 ・Fiber を使う ・Mac(POSIX) の場合 ・ucontext を使う ・Linux の場合 ・アセンブラを使う
  17. 17. Boost.Coroutine の実装 ・環境によってはコンテキストを自由に作れない ・セキュリティ的に問題あり ・だからこそのFiberやucontext ・組み込み環境で特に有効 ・スレッドも使えない上に何ms以内にシステムに返せとか面倒 ・アセンブラで自作できる場合が多い ・BREW 環境上(ARM アセンブラ)で作ってみて無事動いた ・実装を知っておくと好きな環境で作れる
  18. 18. Boost.Coroutine の実装 ・コンテキストとは ・実行するために必要なもの void f(coro_type::self& self) { int a; // a, b はスタックに置かれている int b; // a, b は yield されても保持されている self.yield(); } ・スタック ・レジスタ ・(例外情報) ・これらを保存して実行中のコンテキストを切り替える
  19. 19. Boost.Coroutine の実装 ・コンテキストの切り替え方 1.必要な情報を保存する 2.スタックポインタを書き換える 3.必要な情報を読み込む 4.プログラムカウンタを書き換える
  20. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 42. Boost.Coroutine の未来 ・Boost.ML を追いかけた ・2008/7/26 に sandbox 上の Boost.Coroutine を更新している ・複雑になりすぎたのでもっと単純なインターフェースにするとか何とか ・作者は ML には結構出てきてるのでちゃんと元気にしてるっぽい ・やる気が無い? ・作者以外の人が頑張っている ・Mac 版の対応 ・バグの修正 ・Boost.Coroutine の未来 ・正式に採用されるのかどうか分からない ・Boost.Fiber という対抗馬も最近出てきた
  43. 43. Boost.Coroutine のまとめ ・手動マルチスレッド ・いろいろな使い方ができる ・実装はスタックポインタの書き換え ・それ以外の方法で実装するのもあり ・Boost.Coroutine は実装の模範例 ・利用は自己責任
  44. 44. おわり

×