Apparemment, boost contient deux bibliothèques distinctes pour les machines à états: Statechart et Meta State Machine (MSM). Les slogans donnent des descriptions très similaires:
Savez-vous quelles sont les principales différences et quelles sont les considérations dans le choix entre les deux?
Comme il semble y avoir beaucoup d'intérêt, permettez-moi de donner mon avis (évidemment biaisé), qui doit donc être pris avec un grain de sel:
Vous pouvez vous faire une meilleure opinion en recherchant les commentaires postés lors de la revue de MSM. Ce sujet a été beaucoup discuté sur la liste des développeurs.
Comme Christophe l'a déjà mentionné, l'une des principales différences entre les deux bibliothèques est la performance d'exécution. Alors que MSM offre probablement le meilleur que vous pouvez obtenir ici, Statechart échange consciemment les cycles de mémoire et de processeur vers une meilleure évolutivité.
Avec Boost.Statechart, vous pouvez répartir la disposition (c'est-à-dire les états, les transitions) de votre machine d'état sur plusieurs unités de traduction (fichiers cpp) de différentes manières. ' t avec MSM. Cela vous permet de rendre l'implémentation de grands FSM plus facile à gérer et d'obtenir une compilation beaucoup plus rapide qu'avec MSM.
Il est souvent assez facile de savoir si les frais généraux de performances de Statechart par rapport à MSM seront importants pour votre application lorsque vous vous demandez combien d'événements votre application devra traiter par seconde.
En supposant un FSM modérément complexe implémenté avec Boost.Statechart, voici quelques chiffres approximatifs:
En ce qui concerne la charge du processeur, si le nombre d'événements à traiter est bien inférieur à ces chiffres, la surcharge de Boost.Statechart par rapport à MSM ne sera presque certainement pas perceptible. Si le nombre est beaucoup plus élevé, vous êtes certainement mieux avec MSM.
Des informations plus détaillées sur les compromis performances/évolutivité sont disponibles ici: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html
En codant ma propre PPP implémentation, j'ai utilisé Statechart pour trois raisons: 1) Statechart est plus simple et a une documentation plus claire; 2) Je n'aime vraiment pas UML :)
Les documents Boost indiquent que MSM est au moins 20 fois plus rapide, mais se compile assez lentement pour les grands FSM.
Il y a quelque temps, j'ai commencé avec Statechart et je suis passé à MSM car il était plus facile à utiliser avec asio à partir d'un seul thread. Je n'ai pas réussi à mailler Statechart et ses capacités de multithreading avec mon utilisation de asio - c'était probablement une sorte d'incompréhension pour les débutants de Statechart de ma part. J'ai trouvé que MSM était plus facile à utiliser car il n'abordait pas le multithreading.
En réponse à l'entrée tardive de Tim dans la discussion (qui aborde également l'un des tout premiers commentaires de Lev).
En tant que l'un de ceux qui ont plaidé pour la séparation des sorties des destructeurs dans le diagramme d'états (argument basé sur un cas d'utilisation réel, sur l'interaction avec le monde réel, c'est-à-dire les E/S) depuis le moment où il a été soumis à Boost, je conviens qu'il peut y avoir des problèmes à mettre la sortie logique dans les destructeurs. Sans surprise, David Abrahams a présenté des arguments convaincants concernant la sécurité des exceptions. Pour ces raisons, Statechart ne vous oblige pas à mettre de la logique dans les destructeurs - mais il vous le permet - avec les conseils habituels.
La logique qui ne doit jamais être exécutée que dans le cadre d'une transition hors d'un état (et non la destruction de l'objet de diagramme d'état dans son ensemble) peut (et devrait, s'il y a également un nettoyage des ressources à faire) être séparée en une action exit () distincte.
Pour un état "mince" sans état actif (ressources), il suffit d'effectuer des actions d'entrée/sortie, vous pouvez effectuer ces actions dans ctor et d'tor et vous assurer que le constructeur et le destructeur ne lancent pas. Il n'y a aucune raison pour eux - il n'y a pas d'état pour effectuer RAII - il n'y a aucun mal à ce que la gestion des erreurs à ces endroits déclenche des événements appropriés. Vous devrez peut-être toujours déterminer si vous souhaitez que les actions de sortie qui modifient l'état externe s'exécutent sur la destruction de la machine d'état ... et les mettre en action de sortie si vous ne voulez pas qu'elles se produisent dans ce cas ...
Statechart modélise l'activation comme une instanciation d'un objet, donc si votre constructeur a un vrai travail/activation/instanciation à faire et s'il peut échouer de telle sorte que l'état ne peut pas être entré Statechart prend en charge cela en vous donnant la possibilité de mapper une exception à une un événement. Ceci est géré d'une manière qui élabore la hiérarchie des états à la recherche d'un état externe qui gère l'événement d'exception, de la même manière que la pile se serait déroulée pour un modèle d'appel basé sur la pile d'appels.
Tout cela est bien documenté - je vous suggère de lire les documents et de l'essayer. Je vous suggère d'utiliser des destructeurs pour nettoyer les "ressources logicielles" et de quitter les actions pour effectuer des "actions de sortie réelles".
Il convient de noter que la propagation des exceptions est un peu un problème dans tous les environnements pilotés par les événements, pas seulement les diagrammes d'états. Il est préférable de raisonner et d'inclure les défauts/erreurs dans la conception de votre graphique et si et seulement si vous ne pouvez pas les gérer d'une autre manière, recourez au mappage d'exceptions. Au moins, cela fonctionne pour moi - ymmmv ....