require "al_worker"
ステートマシンを直接サポートします。
各動作を state_STATE_event_EVENT 形式の名前を付けたメソッドとして定義しておき、フレームワークがステート(状態)とイベントによって、適宜選択して呼び出しながら、全体の動作を行うように構成できます。
require "al_worker_tcp" require "al_worker_timer" class Worker1 < AlWorker def initialize2() set_state( "EN" ) @count = 0 @tcp = Tcp.new() @tcp.run( self ) @timer = Timer.periodic( 10 ) @timer.run() { change_state() } end def tcp_say( sock, param ) trigger_event( "SAY", sock ) # イベント "SAY" を発生させる。 return true end def change_state() # 10秒ごとに、ステートを変更する。 case @state when "EN"; set_state( "JP" ) when "JP"; set_state( "DE" ) when "DE"; set_state( "EN" ) end end # ステートが"EN"の時に、"SAY"イベントが発生した時の処理。 def state_EN_event_SAY( sock ) a = ["one","two","three","four","five","six","seven","eight","nine","ten"] sock.puts a[@count] @count = 0 if (@count += 1) > 9 end # ステートが"JP"の時に、"SAY"イベントが発生した時の処理。 def state_JP_event_SAY( sock ) a = ["ichi","ni","san","shi","go","roku","shichi","hachi","kyu","jyu"] sock.puts a[@count] @count = 0 if (@count += 1) > 9 end # ステートが"DE"の時に、"SAY"イベントが発生した時の処理。 def state_DE_event_SAY( sock ) a = ["eins","zwei","drei","vier","fünf","sechs","sieben","acht","neun","zehn"] sock.puts a[@count] @count = 0 if (@count += 1) > 9 end end server = Worker1.new server.daemon
TCPで接続しsayを送るごとに、カウントアップします。
カウントは、10秒ごとに英語、日本語、ドイツ語を切り替えます。
set_state( "STATE" ) # この2つは同じメソッドのaliasです。 next_state( "STATE" )
trigger_event( "EVENT", 任意パラメータ )
優先度 | ハンドラメソッド名 |
---|---|
大 | from_STATE_event_EVENT() |
↑ | state_STATE_event_EVENT() |
↓ | event_EVENT() |
小 | state_STATE() |
条件が重なるハンドラが定義されている場合、上記優先度に従って呼ばれるハンドラが一つ選択されます。
クラス定義中に、na :state_XXX_event_YYY の様に記述します。
Class Worker1 < AlWorker na :state_STATE1_event_EVENT1 end
簡易的にですが、Rubyコードからステート表をリバース生成できるスクリプトを提供しています。
上記サンプルプログラムをパースした例です。
$./make_state_chart.rb state_machine.rb EN JP DE SAY full full full
スクリプト、make_state_chart.rb に、対象プログラムを引数として実行すると、ステートを横軸に、イベントを縦軸にした表を生成します。
表の見方
表示 | 意味 |
---|---|
full | ステート、イベントとも指定されたハンドラが定義されている |
event | イベントのみ指定されたハンドラが定義されている |
state | ステートのみ指定されたハンドラが定義されている |
/ | 無視 (na) するように指定されている |
空欄 | ハンドラが定義されていない |