C言語でコルーチン(co-routine)
Posted by arms22 on 2008年04月07日 0 0C言語でコルーチンを実装してみる。
コルーチン(co-routine)とはプログラミングの構造の一種。サブルーチンがエントリーからリターンまでを一つの処理単位とするのに対し、コルーチンはいったん処理を中断した後、続きから処理を再開できる。接頭辞co-は協調を意味するが、複数のコルーチンが中断/継続により協調動作を行う。
組み込みシステムではよく、複数の処理を同時に行う必要がある。そのような場合、コルーチンが使えれば、処理の記述が楽に行える。switch-caseあるいは関数テーブルなどを駆使すれば、実現することは可能だが、見通しがわるくなる。
コルーチンをサポートする言語にはModula-2、Simula、Icon、Lua、C#がある。マルチスレッドで原理的には同じことができるため、現在はそちらが使われるケースが多い。
組み込みシステムにおいても上記のことは言えるが、小規模なシステムの場合、リソースの制約上、処理1つ1つにタスクを割り当てることができず、1つのタスクで複数の処理を実行するケースも存在する。
今回、紹介するコルーチンはswitch-caseを巧みに利用して実現されている。次のコードは呼び出すごとに"Hello World"がテキトーになっていくHelloWorld関数だ。
void helloworld(void){実行結果は次の通り。
co_begin;
printf("hello world!!\n");
co_yield();
printf("hi world!\n");
co_yield();
printf("hi again.\n");
co_yield();
printf("hi\n");
co_yield();
printf(":)\n");
co_end;
}
main(){
helloworld();
helloworld();
helloworld();
helloworld();
helloworld();
}
hello world!!見慣れないキーワードが三つ。それぞれ簡単に説明すると、
hi world!
hi again.
hi
:)
- co_begin
コルーチンの開始 - co_yield()
処理の中断 - co_end
コルーチンの終了
co_yieldは呼び出した時点で処理を中断し関数を抜けるんだ。次にこの関数が呼ばれた時、最後にco_yieldを呼び出したところから処理が再開される。
さて、気になるco_begin,co_yield(),co_endの実装を見てみよう。
#define co_begin \うーん。なかなか良く出来たコードだ。switch-caseを巧みに利用しているのがわかる。もちろんこのマクロは完璧ではない。ローカル変数は使えないし、外部から状態を制御できない。PICなんかだと、1度動作を開始させた後、処理を止める必要がない場合が多いので、今回のマクロで十分かもしれない。
static int __state = 0; \
switch(__state){ \
case 0:
#define co_yield() \
do { \
__state = __LINE__; \
return; \
case __LINE__: \
break; \
} while(0);
#define co_end \
__state = __LINE__; \
}
次回は、このコルーチンマクロをもう少し使い易く、ローカル変数を使えるようにしてみる。
コルーチン - Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%AB%E3%83%BC%E3%83%81%E3%83%B3
Ads by Google
0 Comments
Leave a reply
該当の記事は見つかりませんでした。