====== ステートマシン ====== 組込みソフトウェアでは、ステートマシンを使って上位設計(モデルベース設計)を行い、それをコードに落とすという設計手法を採用する場合があります。\\ Aloneでは、ステートマシンを直接サポートし、記述性、可読性の向上を実現しています。 ここでは簡単に、2種類のステート (1 or 2)と2種類のイベント (A or B) の、合計4つの場合があることを想定したサンプルを示します。 ^ ^ St 1 ^ St 2 ^ ^ Ev A | handler St1 EvA | handler St2 EvA | ^ Ev B | handler St1 EvB | handler St2 EvB | require "al_worker_tcp" require "al_worker_fd" class Worker1 < AlWorker def initialize2() set_state( :St1 ) @fd = Fd.new(STDIN) @fd.ready_read() { # STDINの行入力イベントハンドラ txt = @fd.file.gets case txt[0] when "1" set_state( :St1 ) puts "DEBUG: change state to :St1" when "2" set_state( :St2 ) puts "DEBUG: change state to :St2" when "A", "a" trigger_event( :EvA ) when "B", "b" trigger_event( :EvB ) end } end # ステートマシンのハンドラ群 def state_St1_event_EvA() puts "state_St1_event_EvA called." end def state_St1_event_EvB() puts "state_St1_event_EvB called." end def state_St2_event_EvA() puts "state_St2_event_EvA called." end def state_St2_event_EvB() puts "state_St2_event_EvB called." end end worker = Worker1.new() puts "Hit 1, 2, A, B (and Enter)" worker.run() ===== 解説 ===== 初期化では、初期状態のステート St1 を宣言しています。 そして、キー入力を使い状態の遷移とイベントの発生を模擬するために、イベントハンドラとして標準入力(STDIN)を使います。 * 1行入力されたらハンドラが動作を開始します。 * 入力文字列の先頭文字が "1"ならば、ステートを St1 に変更します。"2"の場合も同様です。 * 入力文字列の先頭文字が "A"ならば、イベント EvA を発生させ、その時のステートに合致するハンドラが呼び出されます。"B"の場合も同様です。 イベントが発生した場合の各動作は、state_STATE_event_EVENT 形式の名前を付けたメソッドとして定義します。Aloneは、イベントの発生があると、ステート(状態)とイベント種類に応じて適宜選択して呼び出します。 イベントという言葉が、文脈によって2パターンに使い分けられていますので注意してください。 最初の「イベントハンドラ」の場合は、システム(OS)によって発生したイベントの事で、イベントハンドラはブロックとして記述しステートに関係なく呼び出されます。 ステートマシンの「イベント」と言った場合は、イベントは trigger_event()メソッドによって生成され、ハンドラはメソッドとして記述します。