ただ1つのAPIで全イベントの完了を待てるようにした「非同期完了待ち」というデザイン。それを採用した狙いは何なのか?
前回の「並行処理の奥義、非同期フレームワークとは?」に引き続き、Symbian OSにおける非同期フレームワークを解説していきます。
非同期フレームワークは、
の2つに対する抽象化を実現するものです。このうち、非同期要求の抽象化については、
ということを前回説明しました。そこで今回は非同期処理の残り半分、「非同期の完了待ち」について解説していきます。
「非同期の完了待ちなんてどこのOSでもやってる話だし、別に書きたいように書けばいいんじゃないの? Symbian OSでは非同期処理さえやっておけば性能出るんでしょ。大丈夫、オレ前のOSじゃ非同期をきちんと書いてたんだから、前のスタイルでやらせてよ」−という話を、“マレ”では済まされない頻度で耳にします。残念ですが、こんな態度の人が存在すると、そのプロジェクトは破たんしたも同然です。
今回の目的は、もちろんSymbian OSにおける非同期フレームワークを紹介することにあります。しかし、例えばX Window System由来のコードをそのまま移植しようとする破壊分子がプロジェクトに現れたとき、説得(または撃退)する方法を伝えることも、また目的だったりします。え、実はまさにいま、X Window System由来のコードを移植しようとしているのですか? ……引き返す最後のチャンスです。よく注意して読んでください。
ここでもう一度非同期処理のAPIシーケンスを考えてみます。
図1のシーケンス図はプログラムが動いている状態の図(UMLでいう「振る舞い図」)です。では、この動作を満たすプログラムはどんな形になるでしょうか。
複数の非同期要求の完了を、1回の関数発行で待つことができるAPI(以下、完了待ちAPI)が提供されているとします。すると、図1のクライアント側の動作を行う、最もシンプルなコードは以下のように構成できます。
while ( 1 ) { // 完了待ち WaitForAnyRequest (); // 完了判定と対応処理 if ( 「キーボード待ち」完了通知だったら ) { ... 「キーボード待ち」完了処理 ... } else if ( 「受信」完了通知だったら ) { ... 「受信」完了処理 ... } else if ( 「送信」完了通知だったら ) { ... 「送信」完了処理 ... } else if ( ... ) { ... } }
図2 完了待ちの抽象コード |
上記のコードでは、WaitForAnyRequest()が完了待ちAPIになります。この関数の名前などディテールの差異を除けば、この形のプログラムはそれほど奇抜な話ではありません。というより、Win32APIを生でたたいたことがある人や、X Window Systemのプログラムを書いたことがある人には、おなじみのスタイルのコードであるはずです(注1)。
ほかからのイベント(注2)が届くまで何らかの方法で待ち、届いたイベントに対するハンドラを呼び出す。それをプログラムが終わるまで繰り返す。このようなスタイルのコードをウェイトループといいます。非同期に到着したイベントを各ハンドラに振り分けるための、基本的な概念として知られています。基本的な概念? そう、ウェイトループをそのまま実装するには問題があるのです。
Copyright © ITmedia, Inc. All Rights Reserved.