ユーザ用ツール

サイト用ツール


alworker:ステートマシン

AlWorker ステートマシン

require "al_worker"


ステートマシンを直接サポートします。
各動作を state_STATE_event_EVENT 形式の名前を付けたメソッドとして定義しておき、フレームワークがステート(状態)とイベントによって、適宜選択して呼び出しながら、全体の動作を行うように構成できます。

サンプル

state_machine.rb
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) するように指定されている
空欄ハンドラが定義されていない
alworker/ステートマシン.txt · 最終更新: 2019/03/19 11:14 by hirohito