Pergunta

Eu estou procurando algum geral

  1. Otimização
  2. Correção
  3. extensibilidade

conselhos sobre meu atual implementação C ++ Estado hierárquica máquina.

Amostra

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)

Implementação

Atualmente, a HSM é implementado como uma estrutura de árvore onde cada estado pode ter um número variável de estados como crianças.

Cada estado contém um número variável de blocos de "substituição" (em um std :: map) que os valores base de substituição. No estado de raiz, a máquina do Estado tem um conjunto de variáveis ??(funções, propriedades ...) inicializados com alguns valores padrão. Cada vez que entramos em um estado infantil, uma lista de "substituições" definir os valores das variáveis ??e que deve substituir as variáveis ??e valores de mesmo nome no estado pai. Atualizado originais para maior clareza.

variáveis ??referenciação

Durante a execução, os estados atuais são armazenadas em uma pilha.

Cada vez que uma variável é referenciada, uma pilha para baixo caminhada é realizada procurando o maior substituição, ou, no caso de nenhuma sobreposição, o valor padrão.

estados de comutação

Cada vez que um único quadro de estado é comutado para o estado é empurrado para uma pilha.

Cada vez que um estado é comutada para, eu traçar um descension árvore que me leva a partir do estado atual para o estado raiz. Então eu faço um descension árvore do estado de destino para o estado da raiz até eu ver o traço atual corresponde ao traço anterior. Declaro um cruzamento para onde esses 2 vestígios se encontram. Então, para mudar para o estado de destino, eu descer a partir da fonte, popping quadros do estado da pilha até eu chegar ao ponto de intersecção. Ascend Então eu para o nó de destino e estaduais impulso quadros na pilha.

Assim, para o exemplo de código acima

trace de Execução para detector de estado

  • state Fonte = gravação
  • Alvo Estado = alsoStreamToRemoteIp

  • descension a partir da fonte na gravação => raiz (traço = [raiz])

  • descension de alvo = alsoStreamToRemoteIp-> de reprodução> raiz (traço = [reprodução, raiz])

  • Intersects na raiz.

Para alternar de gravação para alsoStreamToRemoteIp,

  1. Pop "gravação" da pilha (e chamar sua função de saída ... não definido aqui).
  2. Push "playback" na pilha (e função chamar a entrar).
  3. Push "alsoStreamToRemoteIp" na pilha (e chamar a função de entrar).
Foi útil?

Solução

Duas coisas:

1:. Para a maioria dos casos apenas representar o estado de seu programa como um modelo, e interagir com ele diretamente ou através do padrão MVC

2: Se você realmente precisa de um FSM, ou seja, você quer fazer aleatoriamente um monte de ações para o seu modelo, das quais apenas algumas são permitidas em determinados momentos. Então ....

Ainda manter o estado de seu programa em um modelo (ou vários modelos dependendo de decomposição e complexidade) e representam estados e transições como.

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

Onde vizinhos contém um dicionário de de {Action: State}, de modo que você pode fazer algo como

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

Ou mesmo mais frio, tem de selecionar um loop infinito aleatoriamente uma ação dos vizinhos, executá-lo, e se movendo estado indefinidamente. É uma ótima maneira de testar seu programa.

Outras dicas

Eu não estou certo de que siga todos os detalhes aqui. No entanto, parece que você está descrevendo uma implementação FSM (finito máquina estatal) onde você tem várias máquinas de estado. Às vezes, quando um determinado evento (E1) ocorre em um determinado estado (S1) do FSM F1, você precisa inserir um novo FSM (chamemos-lhe F2) para simplificar o processamento geral).

Se for esse o caso, então quando E1 ocorre em S1, você precisa chamar uma rotina de ação que assume a leitura evento e implementos a F2 FSM. Quando invocado, ele começa a processar no estado início da F2, e lida com os sub-eventos relevantes. Quando se atinge o seu estado final, o intérprete para F2 termina. Ele pode retornar algumas informações para a rotina de ação F1 que foi suspensa enquanto F2 correu, e o próximo estado na F1 pode ser afetado por isso.

O resto da sua descrição - coisas como 'blocos de substituição' -. Não fará muito sentido para as pessoas sem acesso a sua implementação

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top