連載
» 2007年08月15日 00時00分 公開

Symbian OS開発の勘所(7):画期的な「非同期完了待ち」のフレームワーク (3/3)

[大久保 潤 管理工学研究所,@IT MONOist]
前のページへ 1|2|3       

コードの再利用性はいつでも重要なのか

――話は分かった。でもこのXXXXは実績のあるコードだから、そのままSymbian OSに移植したいんだけど――

 コードの再利用性という神話が、ワレワレの目を曇らせることが少なからずあります。石器時代に再利用性という言葉が幅を利かせていたら、ワレワレはまだ黒曜石のナイフを使って暮らしていたかもしれません。別に黒曜石のナイフに恨みはないのですが、ブレークスルーと再利用性をはかりに掛けると、もちろんですがブレークスルーが優先されるべきです。何しろ第5回にも書いたとおり、組み込みシステムのバイナリサイズはメガバイトオーダーを超えてなお増え続けており、そのため新しいブレークスルーが絶えず要求されています。だから、ほかの環境からのコードのポーティングに際しては、それがSymbian OSが用意したブレークスルーを阻害しないモノであるか否かを真剣に検討する必要があります。その結果、単なるスタイルの相違として片付けられる問題であれば再利用性を取るのも故なきことではありません。

 ではXXXXの移植が妥当なのか否か。それを判断するために、非同期の完了待ちに関するほかのOSとSymbian OSの間のギャップを検討します。

このコードの問題は何か?

 まずはX Window Systemにおけるウェイトループの例を見てみます。赤く囲ってあるコードに注目です。

X Window Systemのウェイトループ例 図7 X Window Systemのウェイトループ例

 usleep()はマイクロセカンドの分解能を持つスリープ関数です。だから上のコードは50msに1回目を覚まして、Xに関するイベントが到着していないかをうろうろ探すことになります。もっとはっきりいうと、上のコードを使った場合、何らのイベントが発生していなくてもスレッドは起床を繰り返し、貴重な電力を消費し続けます。完了通知が発生するまでAPIからリターンしてこないSymbian OSのデザインと対照的です(そしてSymbian OSではすべてのプログラムが非同期の完了待ちを行うので、イベントが発生しなくなると容易に省電力モードに移行できます)。

本当に大事なことは統合されているということ

――でもWindowsのコードとか、POSIX系でもソケット回りに限ってなら問題はないんじゃないの?――

 Symbian OSの完了待ちAPI、User::WaitForAnyRequest()(CActiveScheduler::WaitForAnyRequest()の中核で発行されているAPI)が本当にすごいのは、すべてのイベントを1カ所で待てる点にあります。

 例えばPOSIX系だとどうでしょう。select()でネットワーク回りを多重待ちできたとしても、同じAPIで非同期ファイルI/Oが扱えないのであれば意味がありません。POSIXの非同期I/O仕様であるaio_関数群はaio_suspend()というAPIで多重に待つことができますが、それらの識別子はFD(File Descriptor)ではありません。つまり1つのスレッドでネットワークと非同期ファイルI/Oを同時に扱おうとした場合、select()とaio_suspend()を交互に出し分けつつウェイトループを回す必要があります。

 1カ所で待てるSymbian OSの場合、完了待ちAPIは基本的にタイムアウトなしの無限待ちとなりますが、複数の完了待ちAPIを出し分けるとすると無限待ちというわけにはいきません。CPUの負荷を上げ過ぎないように、かつ待っているイベントの到着間隔に適合するように、適切(おお、何と便利な言葉でしょう)なタイムアウト値を設定し、完了待ちAPIを発行する必要があります。

 このように複数の完了待ちAPIの細かな出し分けとは、結局のところユーザーランドでのポーリングと等価な行為です。X Window Systemを使わなくても、スレッドが周期的に起床されてしまうのです(ポーリングとはユーザーランドが無限にCPUを使い得るというナイーブな仮定に基づくナイーブなスタイルなので、それを採用した以上、CPUと貴重な電源を食い散らかされるのは自明である、ということもできます)。

 以下に、各OSにおける非同期イベントの統合の程度を示します。

<Windows>
・MsgWaitForMultipleObjectsEx()により、メッセージと各種イベントが同時に待ち合せ可能(システムの要素をほぼカバー)
・ただしネットワークに対する非同期I/Oの完了はWSPGetOverlappedResult()が必要

<POSIX系+X Window System>
・割合にバラバラ
・FD系、aio_系、X Event系でそれぞれAPIの出し分けが必要

 Windowsの場合、ネットワークに関する通知はワーカスレッドでいったん受けて、そこでイベントに変換してからメインスレッドに投げ直すという方法で、ウェイトを1カ所に集約することが可能です。が、そんな変換のためにスレッドを使うのはコストが高過ぎます。これもまた輸入禁止品目に該当するでしょう。

 このように完了待ちAPIの対象イベントが統一されていない場合、システム全体に対してさまざまな負荷が発生します。特にポーリングが発生することによる電力の浪費は致命的で、携帯電話・スマートフォン向きのコードにはふさわしくありません。再利用性は確かに重要ですが、電力消費のことを考えていないプログラムはそもそもリクワイヤメントを満たしていないのですから、そんなモノをいくら移植したところで生産性も品質も向上することはありません。移植しようとしていたXXXXというコードはこれらの問題点を免れているのでしょうか。



 前回、今回と2回に分けてSymbian OSの非同期処理について解説してきました。Symbian OSにおいては、アクティブオブジェクトにより非同期処理が手軽に書けるようになり、アクティブスケジューラによりウェイトに関する些事(さじ)が解消されています。それを可能にしているのは、ただ1つの完了待ちAPIですべてのイベントを待てるようにしようというデザイン上の決定です(注4)。これによりポーリングスタイルのコードが廃絶でき、携帯電話・スマートフォンに必要な省電力性までもが確保されています。

 よくできたデザインのAPIをオブジェクト指向のフレームワークでラップし、携帯電話・スマートフォン向けの高性能・高品質の環境を実現するというSymbian OSの思想は、非同期処理においてもこのように徹底されています。

 次回は3大ポイントの3番目、クライアントサーバについて解説を行います。(次回に続く)


※注4:
管理工学社内ではコレを称して「統一場理論に基づくOS」と呼ぶことがあります。I/O、GUI、そのほかもろもろがすべてイベントとして等価に扱えるようになっているためです。


前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.