では、Protothreadsはこれをどうやって実現しているのか。その種明かしが図7になる。「インプリメントは6行」などと自慢しているが、実際にProtothreadsの全体はpt.hの中に格納されており、しかも本当に6行である。もっとも図7のコードはやや古いバージョンのもので、最新バージョンだともう少し複雑だしAPIも増えている(PT_SPAWN()やPT_RESTART()なども追加されており、関数(?)は全部で13個になっている)が、基本は同じである。
これは全部C言語のマクロだから、プリプロセッサを通すと図8のように展開される。最初に「Fiberもどき」と書いたのは、要するにこれはPreemptiveもへったくれもなく、実際にはSingle Task/Process/Threadで動作しているにもかかわらず、あたかもMulti Task/Process/Threadで動いているかのように見せかけているわけである。
ではこれにどんなメリットがあるのか。例えば、ワイヤレスでの通信の後に一定期間スリープすることで消費電力を削減するという、よくあるコードを普通に書くと図9のようになるが、Protothreadsを使うと図10のレベルまでシンプル化できる。可読性が上がるし、メンテナンスもしやすい。もちろんこれ、デバッガを使ってステップ動作で追っかけている時にはちょっと「?」になりそうだが、慣れればそれほど苦にはならないだろう。
この可読性が向上する(=複雑性が減る)というのはばかにならない効果であって、実際いろいろなドライバ類やコードにProtothreadsを使った際の効果も出ている(図11)。
コード数だけでなく、StateやTransitionの数も減らすことができており、効果は大きい。代償は、若干のコードサイズ増加(図12)と処理サイクル増加(図13)である。
200バイトも増えるのは問題では? と思うかもしれないが、これはコードサイズ(つまりROM側)であってRAM側の増加ではない。RAM側の方は、PT_BEGIN()を呼び出す際にunsigned shortの領域を1つ使うから、PT_BEGIN()を複数並行して使うようなケースではその数×2バイトの増加だが、これは大きな問題にならない範囲だし、処理サイクルのオーバーヘッドも言うほどには大きくない。メリットとデメリットを勘案すれば、許容できる範囲かと思う。
Protothreadsの開発は2006年に終了しているが、最新版(v1.4:pt.hはv1.7)はDunkels氏のサイトから入手できる。しかもアーキテクチャ依存性もなく、ANSI Cに準拠したコンパイラを使える環境ならどこでも稼働する。実際AVR/PIC/MSP430/Arm/x86で動作するから、例えばWindowsのアプリケーションをVisual StudioでC++を使って記述するときにProtothreadsを利用することすら可能である。
単独で利用する、というよりも既存のRTOS上での開発の際に、Protothreadsを組み合わせる、という使い方が便利そうである。ちなみにライセンスはOpen source BSD-style licenseで提供されており、ライセンス表記だけをしておけば、商用製品に使うこともできる。実装はシンプルだが、RTOSと非常に相性の良いライブラリ、といえるだろう。
Copyright © ITmedia, Inc. All Rights Reserved.