Frage

Ich bin für einige allgemeine Suche

  1. Optimierung
  2. Correctness
  3. Extensibility

Beratung auf meiner aktuellen C ++ Hierarchical State Machine-Implementierung.

Beispiel

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)

Implementierung

Derzeit wird der HSM als Baumstruktur implementiert, wobei jeder Staat eine variable Anzahl von Staaten als Kinder hat.

Jeder Zustand enthält eine variable Anzahl von „überschreibt“ Blöcke (in einem std :: map) außer Kraft Basiswert. An der Wurzel Zustand weist die Zustandsmaschine einen Satz von Variablen (Funktionen, Eigenschaften ...) zu einigen Standardwerten initialisiert. Jedes Mal, wenn wir geben ein Kind Zustand, eine Liste von „Überschreibungen“ definieren Variable und Werte, die die Variablen und Werte mit dem gleichen Namen in dem übergeordneten Zustand ersetzen sollen. Aktualisiert original für Klarheit.

Referenzierung Variablen

Zur Laufzeit werden die aktuellen Zustände auf einem Stapel abgelegt.

Jedes Mal, wenn eine Variable verwiesen wird, ein nach unten Stapel zu Fuß sucht die höchste Überschreibung durchgeführt wird, oder im Fall von nicht überschreibt, der Standardwert.

Schaltzustände

Jedes Mal, wenn ein einzelner Zustandsrahmen umgeschaltet wird, wird der Zustand auf einen Stapel geschoben.

Jedes Mal, wenn ein Zustand geschaltet wird, ich einen Baum descension verfolgen, die mich aus dem aktuellen Zustand in dem Root-Zustand annimmt. Dann mache ich einen Baum descension vom Sollzustand an die Wurzel Zustand, bis ich die aktuelle Trace entspricht die vorherige Spur zu sehen. Ich erkläre, eine Kreuzung auf, wo diese zwei Spuren entsprechen. Dann, um den Zielzustand zu wechseln, steige I von der Quelle, Zustandsrahmen aus dem Stapel popping bis ich den Schnittpunkt erreichen. Dann habe ich an den Zielknoten aufzusteigen und Zustandsrahmen auf den Stapel schieben.

Also für das Codebeispiel oben

Execution Trace für Leiterschalter

  • Quelle state = Aufnahme
  • Ziel State = alsoStreamToRemoteIp

  • descension von source = Recording-> root (trace = [root])

  • descension von target = alsoStreamToRemoteIp-> Wiedergabe-> root (trace = [Wiedergabe root])

  • durchteuft an der Wurzel.

Zum Umschalten von zu alsoStreamToRemoteIp Aufnahme

  1. Pop „Aufnahme“ aus dem Stapel (und seine Exit-Funktion aufrufen ... hier nicht definiert sind).
  2. Push „Wiedergabe“ auf den Stapel (und rufen Sie die Enter-Funktion).
  3. Push "alsoStreamToRemoteIp" auf den Stapel (und rufen die die Enter-Funktion).
War es hilfreich?

Lösung

Zwei Dinge:

. 1: Für die meisten Fälle stellen nur den Zustand Ihres Programms als Model, und mit ihm interagieren direkt oder über das MVC-Muster

2: Wenn Sie wirklich eine FSM benötigen, das heißt Sie wollen zufällig eine Reihe von Aktionen zu Ihrem Modell machen, von denen nur einige zu bestimmten Zeiten erlaubt sind. Dann ....

halten

Still den Zustand Ihres Programms in einem Modell (oder mehrere Modelle je nach Zersetzung und Komplexität) und repräsentieren Zustände und Übergänge mögen.

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

Wo Nachbarn ein Wörterbuch von {Action: State} enthält, so dass Sie so etwas wie

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

Oder sogar kühle, haben eine Endlosschleife zufällig eine Aktion von den Nachbarn der Auswahl, Ausführung es, und auf unbestimmte Zeit Zustand zu bewegen. Es ist eine gute Möglichkeit, Ihr Programm zu testen.

Andere Tipps

Ich bin mir nicht sicher, ob ich alle Details folgen hier. Allerdings scheint es, dass Sie einen FSM (Finite State Machine) Implementierung beschreiben, wo Sie mehrere Zustandsmaschinen haben. Manchmal, wenn ein bestimmtes Ereignis (E1) tritt in einem bestimmten Zustand (S1) von FSM F1, müssen Sie eine neue FSM eingeben (nennen wir es F2) insgesamt um die Verarbeitung zu vereinfachen).

Wenn das der Fall ist, dann, wenn E1 in S1 auftritt, müssen Sie eine Aktion Routine aufzurufen, die das Ereignis Lesen übernimmt und implementiert die F2 FSM. Wenn es aufgerufen wird, startet er die Verarbeitung in dem Startzustand von F2 und verarbeitet die jeweiligen Teilveranstaltungen. Wenn es seinen Endzustand erreicht hat, beendet der Dolmetscher für F2. Es könnte einige Informationen an die F1 Aktionsroutine zurück, die ausgesetzt wurde, während F2 lief, und der nächste Zustand in der Formel 1 kann davon betroffen sein.

Der Rest der Beschreibung - Sachen wie ‚Blockierungen überschreiben.‘ - nicht viel Sinn für Menschen ohne Zugang zu Ihrer Implementierung machen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top