Hatena::ブログ(Diary)

Garbage Collection

2012-02-20

コルーチンのお話

以前、こんなネタを書いていました
C++でコルーチンを使う、というものです

http://blogs.wankuma.com/izmktr/archive/2010/04/28/188507.aspx

わんくまはよく落ちるので、上の記事にあるソースを転載しておきます

#include "coroutine.h"

class Test:public Coroutine{
 int i;

public:
 bool Foo(){
  CoroutineBegin();
  for (i = 1; i <= 20; i++){
   printf("%d ", i);
   yield;
   if ((i % 3) == 0){
    printf("fizz ");
    yield;
   }
   if ((i % 5) == 0){
    printf("buzz ");
    yield;
   }
  }
  CoroutineEnd();
  return true;
 }

};

int _tmain(int argc, _TCHAR* argv[])
{
 Test test;
 for (;;){
  bool finish = test.Foo();
  if (finish) break;
  printf("---\n");
 }

 return 0;
}

これを動かすと、test.Foo()ってのが、あたかもコルーチンっぽく動くのです

うまく隠蔽しているので一見すごい!と思ってしまうのですが、
その隠蔽していたヘッダファイルが以下になります

#ifndef CoroutineHeader
#define CoroutineHeader

class Coroutine{
protected:
    int state;
public:
    Coroutine():state(0){}
    virtual ~Coroutine(){}
};

#define CoroutineBegin() switch(state){case 0:
#define CoroutineEnd()   default: break;}
#define yield {state = __LINE__; return false; case __LINE__:;}

#endif

関数に見えたCoroutineBegin(), CoroutineEnd()はマクロで、
中身はただのswitch文です

つまり、returnする直前にreturnの次の行のジャンプポイントをstateに保存しておき、
次回関数が呼ばれた時にswitch文でreturnの次の行にジャンプするわけです

書いた当時は「ちょwwおまwww」というコメントを期待してたのですが無反応だし、
更にネタを投下したのにやっぱり無反応で寂しい思いをしてたのですが、
まさか、1年以上経って真面目に欲しいということで復刻するとは思いませんでしたね…

exixsexixs 2012/02/28 02:17 以前の者です。
参考になります。ありがとうございます!
にしてもマクロとスイッチにこんな使い方会ったとは…

isobe1978isobe1978 2013/01/24 21:12 これは!!!すごいですね。これでyieldの引数に「進捗率」を指定してreturn falseの代わりにそれを返すようにして、コルーチンを呼ぶ側で多数のコルーチンを束ねて進捗などに応じて都度ディスパッチするようにすればリアルタイムOSみたいなことができますね。

isobe1978isobe1978 2013/01/24 21:16 yieldの引数じゃなくてCoroutineのpublicメンバでもいいのか。ってかCoroutineのpublicメンバに色々機能付け足していくこともできますね。すごい。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/izmktr/20120220/1329745486