Aparentemente, o boost contém duas bibliotecas separadas para máquinas de estado: Statechart e Meta State Machine (MSM). Os slogans dão descrições muito semelhantes:
- Boost.Statechart - Máquinas de estado finito arbitrariamente complexas podem ser implementadas em código C ++ de fácil leitura e manutenção.
- Meta State Machine - Uma biblioteca de alto desempenho para máquinas de estado finito UML2 expressivas.
Você sabe quais são as principais diferenças e quais são as considerações na escolha entre as duas?
c++
boost
state-machine
boost-statechart
boost-msm
FireAphis
fonte
fonte
Respostas:
Como parece haver muito interesse, permita-me dar minha opinião (obviamente tendenciosa), que deve, portanto, ser tomada com um grão de sal:
Você pode ter uma opinião melhor procurando comentários publicados durante a revisão do MSM. Este assunto foi muito discutido na lista de desenvolvedores.
fonte
Como Christophe já mencionou, uma das principais diferenças entre as duas bibliotecas é o desempenho em tempo de execução. Embora o MSM provavelmente ofereça o melhor que você pode obter aqui, o Statechart troca conscientemente os ciclos de memória e processador para uma melhor escalabilidade.
Com o Boost.Statechart, você pode espalhar o layout (ou seja, estados, transições) da sua máquina de estado por várias unidades de tradução (arquivos cpp) de maneiras que não é possível com o MSM. Isso permite que você torne a implementação de FSMs maiores mais sustentável e obtenha uma compilação muito mais rápida do que com o MSM.
Se a sobrecarga de desempenho do Statechart, comparada ao MSM, será realmente significativa para o seu aplicativo, é bastante fácil responder quando você se pergunta quantos eventos o aplicativo deve processar por segundo.
Supondo que um FSM moderadamente complexo seja implementado com o Boost.Statechart, aqui estão alguns números aproximados:
Em relação à carga da CPU, se o número de eventos a processar for muito menor que esses números, a sobrecarga do Boost.Statechart em comparação com o MSM quase certamente não será perceptível. Se o número for muito maior, você definitivamente estará melhor com o MSM.
Informações mais detalhadas sobre as compensações de desempenho / escalabilidade podem ser encontradas aqui: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html
fonte
Ao codificar minha própria implementação de PPP, usei o Statechart por três razões: 1) O Statechart é mais simples e possui documentação mais clara; 2) Eu realmente não gosto da UML :)
Os documentos do Boost dizem que o MSM é pelo menos 20 vezes mais rápido, mas é muito lento para o FSM grande.
fonte
Algum tempo atrás, comecei com o Statechart e mudei para o MSM porque era mais fácil usar em conjunto com o asio a partir de um único thread. Não consegui mesclar o Statechart e seus recursos de multithreading com o uso do asio - provavelmente era algum tipo de incompreensão de novato do Statechart da minha parte. Eu descobri que o MSM era mais fácil de usar, pois não tratava de multithreading.
fonte
Em resposta à entrada tardia de Tim na discussão (que também aborda um dos primeiros comentários de Lev).
Como um dos que defenderam a separação de saída dos destruidores no gráfico de estados (argumento baseado em um caso de uso real, sobre a interação com o mundo real, isto é, E / S), quando foi submetido ao Boost, concordo que pode haver problemas para colocar o exit lógica em destruidores. David Abrahams, sem surpresa, também apresentou argumentos persuasivos em relação à segurança de exceções. Por esses motivos, o Statechart não exige que você coloque lógica nos destruidores - mas permite - com os conselhos habituais.
A lógica que só deve ser executada como parte de uma transição para fora de um estado (não a destruição do objeto do gráfico de estados como um todo) pode (e deve, se houver também limpeza de recursos a fazer) ser separada em uma ação exit () separada.
Para um estado "thin" sem estado ativo (recursos), apenas ações de entrada / saída a serem executadas, você pode executar essas ações no ctor e no d'tor e garantir que o construtor e o destruidor não atinjam. Não há motivo para eles - não há estado para executar a RAII - não há mal em fazer com que o tratamento de erros nesses locais crie eventos apropriados. Talvez você ainda precise considerar se deseja que as ações de saída que alteram o estado externo sejam executadas na destruição da máquina de estado ... e as coloque em ação de saída se não desejar que ocorram nesse caso ...
O Statechart modela a ativação como instanciação de um objeto, portanto, se o seu construtor tem trabalho / ativação / instanciação real a fazer e se é capaz de falhar de modo que o estado não possa ser inserido, o Statechart suporta isso, oferecendo a capacidade de mapear uma exceção para um objeto. evento. Isso é tratado de uma maneira que elabore a hierarquia de estados procurando um estado externo que lide com o evento de exceção, análogo ao modo como a pilha teria se desenrolado para um modelo de chamada baseado em pilha de chamadas.
Tudo isso está bem documentado - sugiro que você leia os documentos e tente. Sugiro que você use destruidores para limpar "recursos de software" e sair de ações para executar "ações de saída do mundo real".
Vale notar que a propagação de exceção é um pouco problemática em todos os ambientes controlados por eventos, não apenas nos gráficos de estados. É melhor raciocinar e incluir falhas / erros no design do gráfico de estados e, se e somente se você não puder lidar com eles de outra maneira, recorra ao mapeamento de exceções. Pelo menos isso funciona para mim - ymmmv ....
fonte