Aparentemente, boost contiene dos bibliotecas separadas para máquinas de estado: Statechart y Meta State Machine (MSM). Los lemas dan descripciones muy similares:
- Boost.Statechart: se pueden implementar máquinas de estado finito arbitrariamente complejas en código C ++ fácil de leer y mantener.
- Meta State Machine: una biblioteca de muy alto rendimiento para máquinas de estados finitos UML2 expresivos.
¿Sabes cuáles son las diferencias clave y cuáles son las consideraciones al elegir entre los dos?
c++
boost
state-machine
boost-statechart
boost-msm
FireAphis
fuente
fuente
Respuestas:
Como parece haber mucho interés, permítame dar mi opinión (obviamente sesgada), que por lo tanto debe tomarse con un grano de sal:
Puede hacerse una mejor opinión buscando comentarios publicados durante la revisión de MSM. Este tema fue muy discutido en la lista de desarrolladores.
fuente
Como ya ha mencionado Christophe, una de las diferencias clave entre las dos bibliotecas es el rendimiento en tiempo de ejecución. Si bien MSM probablemente ofrece lo mejor que puede obtener aquí, Statechart intercambia conscientemente los ciclos de memoria y procesador hacia una mejor escalabilidad.
Con Boost.Statechart puede distribuir el diseño (es decir, estados, transiciones) de su máquina de estado en varias unidades de traducción (archivos cpp) de formas que no puede hacerlo con MSM. Esto le permite hacer que la implementación de FSM grandes sea más fácil de mantener y obtener una compilación mucho más rápida que con MSM.
Si la sobrecarga de rendimiento de Statechart en comparación con MSM será realmente significativa para su aplicación, a menudo es bastante fácil de responder cuando se pregunta cuántos eventos tendrá que procesar su aplicación por segundo.
Suponiendo un FSM moderadamente complejo implementado con Boost.Statechart, aquí hay algunos números de estadio:
Con respecto a la carga de la CPU, si el número de eventos a procesar es mucho menor que estos números, la sobrecarga de Boost.Statechart en comparación con MSM seguramente no se notará. Si el número es mucho mayor, definitivamente estás mejor con MSM.
Puede encontrar más información detallada sobre las compensaciones de rendimiento / escalabilidad aquí: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html
fuente
Mientras codificaba mi propia implementación de PPP, utilicé Statechart por tres razones: 1) Statechart es más simple y tiene una documentación más clara; 2) Realmente no me gusta UML :)
Los documentos de Boost dicen que MSM es al menos 20 veces más rápido, pero se compila bastante lento para FSM grandes.
fuente
Hace algún tiempo comencé con Statechart y me mudé a MSM porque era más fácil de usar junto con asio desde un solo hilo. No logré mezclar Statechart y sus capacidades de subprocesamiento múltiple con mi uso de asio; probablemente fue una especie de incomprensión novata de Statechart de mi parte. Descubrí que MSM era más fácil de usar ya que no abordaba el subprocesamiento múltiple.
fuente
En respuesta a la entrada tardía de Tim a la discusión (que también aborda uno de los primeros comentarios de Lev).
Como uno de los que abogó por la separación de la salida de los destructores en el diagrama de estado (argumento basado en un caso de uso real, sobre la interacción con el mundo real, es decir, E / S) cuando se envió a Boost, estoy de acuerdo en que puede haber problemas al poner la salida lógica en destructores. Como era de esperar, David Abrahams también hizo argumentos persuasivos con respecto a la seguridad de excepción. Por esas razones, Statechart no requiere que coloque la lógica en los destructores, pero se lo permite, con los consejos habituales.
La lógica que solo debería ejecutarse como parte de una transición fuera de un estado (no la destrucción del objeto de diagrama de estado en su conjunto) puede (y debería hacerlo si también hay que hacer una limpieza de recursos) en una acción de salida () separada.
Para un estado "delgado" sin estado activo (recursos), solo acciones de entrada / salida para realizar, puede realizar esas acciones en ctor y d'tor y asegurarse de que el constructor y el destructor no se ejecuten. No hay ninguna razón para que lo hagan, no hay un estado en el que realizar RAII, no hay nada malo en que el manejo de errores en estos lugares genere eventos apropiados. Sin embargo, es posible que deba considerar si desea que las acciones de salida que alteran el estado externo se ejecuten en la destrucción de la máquina de estado ... y ponerlas en acción de salida si no desea que ocurran en este caso ...
Statechart modela la activación como instanciación de un objeto, por lo que si su constructor tiene trabajo real / activación / instanciación que hacer y si puede fallar de tal manera que no se pueda ingresar el estado, Statechart lo respalda al darle la capacidad de asignar una excepción a un evento. Esto se maneja de una manera que funciona en la jerarquía de estado buscando un estado externo que maneje el evento de excepción, de forma análoga a la forma en que la pila se habría desenrollado para un modelo de invocación basado en la pila de llamadas.
Todo esto está bien documentado. Te sugiero que leas los documentos y lo pruebes. Le sugiero que use destructores para limpiar "recursos de software" y acciones de salida para realizar "acciones de salida del mundo real".
Vale la pena señalar que la propagación de excepciones es un problema en todos los entornos controlados por eventos, no solo en los gráficos de estado. Es mejor razonar e incluir fallas / errores en el diseño de su diagrama de estado y si y solo si no puede manejarlos de otra manera recurra al mapeo de excepciones. Al menos eso funciona para mí, ymmmv ...
fuente