なんでも作っちゃう、かも。

Arduino/Make/フィジカルコンピューティング/電子工作あたりで活動しています。スタバの空きカップを使ったスタバカップアンプなど製作。最近はもっぱらArduinoと3Dプリンタの自作に興味があります。

C言語でコルーチン(co-routine)(3)

Posted by arms22 on 2008年04月11日 0  0

C言語でコルーチンを実装してみる、その3。
前回でローカル変数の問題、状態を制御できない問題は解決した。今回はコルーチンで値を返す処理を追加した。例によって、まずはサンプルコードから。

int num_gen(coroutine_t coro)
{
co_begin_rettype(coro,int);
co_local_valiables{
int number;
};
co_local.number = 0;
while(1){
co_yield_ret(co_local.number++);
}
co_end;
}

int main(int argc, char *argv[])
{
coroutine_t gen1;
coroutine_t gen2;
int stack1[128];
int stack2[128];
int i;

gen1 = co_create(num_gen,0,stack1,sizeof(stack1));
gen2 = co_create(num_gen,0,stack2,sizeof(stack2));

for(i=0;i<10;i++){
co_call(gen1);
co_call(gen2);
printf("gen1 result %d,gen2 result %d\n",
co_get_retval(gen1,int),
co_get_retval(gen2,int));
}
}
実行結果は次の通り。
% a.exe
gen1 result 0,gen2 result 0
gen1 result 1,gen2 result 1
gen1 result 2,gen2 result 2
gen1 result 3,gen2 result 3
gen1 result 4,gen2 result 4
gen1 result 5,gen2 result 5
gen1 result 6,gen2 result 6
gen1 result 7,gen2 result 7
gen1 result 8,gen2 result 8
gen1 result 9,gen2 result 9
num_gen関数はint型の値を、呼び出し毎に1ずつ増やして返す関数だ。今回追加したマクロはco_begin_rettype,co_yield_ret,co_get_retvalだ。順番に見ていこう。
  • co_begin_rettype(coro,int);
    コルーチンの開始と戻り値の型を決める。戻り値のサイズ分、スタックに空きを作る。
  • co_yield_ret(co_local.number++);
    スタックに戻り値を積んで、処理を中断し呼び出しもとに戻る。
  • co_get_retval(gen1,int)
    コルーチンの戻り値を型を指定して取り出す。
気になる(?)実装は次の通り。
#define co_begin_rettype(coro,type) \
type *__return_addr = (type*)((coro)+1); \
co_stack_t __stack_addr = (co_stack_t)(((int)(__return_addr+1)+3)&~3); \
switch((coro)->resume){ \
case CO_INITIALALIZE:;

#define co_yield_ret(value) \
do{ \
*__return_addr=value; \
return(__LINE__); \
case __LINE__:; \
}while(0)

#define co_get_retval(coro,type) \
(*((type*)((coro)+1)))
ローカル変数で使うスタックのアライメントを4バイトに調節している。

Ads by Google

Leave a reply






管理者にだけ表示を許可する

該当の記事は見つかりませんでした。