質問

一般的なものを探しています

  1. 最適化
  2. 正しさ
  3. 拡張性

現在のC ++階層状態マシンの実装に関するアドバイス。

サンプル

variable isMicOn = false
variable areSpeakersOn = false
variable stream = false
state recording
{
        //override block for state recording
        isMicOn = true //here, only isMicOn is true              
        //end override block for state recording
}
state playback
{
        //override block for state playback
        areSpeakersOn = true //here, only areSpeakersOn = true
        //end override block for state playback
        state alsoStreamToRemoteIp
        {
                //override block for state alsoStreamToRemoteIp
                stream = true //here, both areSpeakersOn = true and stream = true
                //end override block for state alsoStreamToRemoteIp
        }
}

goToState(recording)
goToState(playback)
goToState(playback.alsoStreamToRemoteIp)

実装

現在、HSMは、各状態が子として可変数の状態を持つことができるツリー構造として実装されています。

各状態には、可変数の「オーバーライド」が含まれます。基本値をオーバーライドするブロック(std :: map内)。ルート状態では、ステートマシンにはいくつかのデフォルト値に初期化された変数(関数、プロパティ...)のセットがあります。子状態に入るたびに、「オーバーライド」のリストが表示されます。親状態の同じ名前の変数と値を置き換える変数と値を定義します。明確にするためにオリジナルを更新しました。

変数の参照

実行時に、現在の状態はスタックに保存されます。

変数が参照されるたびに、最も高いオーバーライドを探して、またはオーバーライドがない場合はデフォルト値を探して、下方へのスタックウォークが実行されます。

状態の切り替え

単一の状態フレームが切り替えられるたびに、状態はスタックにプッシュされます。

状態が切り替わるたびに、現在の状態からルート状態に至るツリーの下降をトレースします。次に、現在のトレースが前のトレースと一致するまで、ターゲット状態からルート状態へのツリーの下降を行います。これら2つのトレースが交わる場所で交差点を宣言します。次に、ターゲット状態に切り替えるために、ソースから降りて、交点に到達するまでスタックから状態フレームをポップします。次に、ターゲットノードまで上昇し、状態フレームをスタックにプッシュします。

つまり、上記のコードサンプルの場合

状態切り替えの実行トレース

  • ソースの状態=記録
  • ターゲット状態= alsoStreamToRemoteIp

  • ソースからの降下= recording-> root(trace = [root])

  • ターゲットからの降下= alsoStreamToRemoteIp-> playback-> root(trace = [playback、root])

  • ルートで交差します。

記録からalsoStreamToRemoteIpに切り替えるには、

  1. ポップ"録音"スタックから(およびその終了関数を呼び出します...ここでは定義されていません)。
  2. プッシュ"再生"スタックに追加します(そして、Enter関数を呼び出します)。
  3. プッシュ" alsoStreamToRemoteIp"スタックに追加します(そしてEnter関数を呼び出します)。
役に立ちましたか?

解決

2つのこと:

1:ほとんどの場合、プログラムの状態をモデルとして表現し、直接またはMVCパターンを介してプログラムと対話します。

2:本当にFSMが必要な場合、つまり、モデルに対して一連のアクションをランダムに行いたい場合、特定の時間に許可されるのはその一部のみです。その後......

プログラムの状態をモデル(または分解と複雑さに応じて複数のモデル)に保持し、状態と遷移を表します。

class State:
   def __init__(self):
      self.neighbors = {}

隣人が {Action:State} の辞書を含む場合、次のようなことができます

someAction.execute() # Actions manipulate the model (use classes or lambdas)
currentState = currentState.neighbors[someAction]

さらにクールなのは、無限ループを使用して、近隣からアクションをランダムに選択し、実行し、状態を無期限に移動することです。プログラムをテストするのに最適な方法です。

他のヒント

ここですべての詳細を確認するかどうかはわかりません。ただし、複数のステートマシンがあるFSM(有限状態マシン)の実装を説明しているようです。場合によっては、FSM F1の特定の状態(S1)で特定のイベント(E1)が発生すると、全体の処理を簡素化するために新しいFSMを入力する必要があります(F2と呼びます)。

その場合、S1でE1が発生すると、イベント読み取りを引き継いでF2 FSMを実装するアクションルーチンを呼び出す必要があります。呼び出されると、F2の開始状態で処理を開始し、関連するサブイベントを処理します。終了状態に達すると、F2のインタープリターは終了します。 F2の実行中に中断されたF1アクションルーチンに情報を返すことがあり、F1の次の状態がその影響を受ける可能性があります。

説明の残りの部分(「ブロックのオーバーライド」など)は、実装にアクセスできない人にはあまり意味がありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top