Les machines d'état en C
Quelle est la meilleure façon d'écrire une machine d'état dans C?
J'ai l'habitude d'écrire une instruction de cas switch dans un for(;;), avec des rappels à ré-entrer dans l'état de la machine lorsqu'une opération est terminée.
Connaissez-vous un moyen plus efficace?
Cela semble assez standard approche de mise en œuvre.
Hey! Qui sonne comme ce que je fais. Le monde est petit.
Hey! Vous avez volé mon code et l'a copié!
Voir ma réponse à stackoverflow.com/questions/1371460/state-machines-tutorials - je pense que la table-driven approche est plus efficace (code de la maintenance et de la lisibilité de point de vue) que l'un big switch
J'ai aussi posté quelques macro-magie ici: stackoverflow.com/questions/1647631/c-state-machine-design/...
Hey! Qui sonne comme ce que je fais. Le monde est petit.
Hey! Vous avez volé mon code et l'a copié!
Voir ma réponse à stackoverflow.com/questions/1371460/state-machines-tutorials - je pense que la table-driven approche est plus efficace (code de la maintenance et de la lisibilité de point de vue) que l'un big switch
J'ai aussi posté quelques macro-magie ici: stackoverflow.com/questions/1647631/c-state-machine-design/...
OriginalL'auteur Maurizio Reginelli | 2010-02-16
Vous devez vous connecter pour publier un commentaire.
J'aime la Bond De Géant approche.
L'état actuel est un pointeur vers une fonction qui prend un objet d'événement comme argument. Lorsqu'un événement se produit, il suffit d'appeler la fonction d'état avec l'événement; La fonction peut alors faire son travail et la transition vers un autre état, par la seule définition de l'état à une autre fonction.
E. g.:
La QL cadres fournit des aides pour des choses comme entrée/sortie/init actions, hiérarchisée de l'état des machines, etc. Je recommande fortement le livre pour une explication plus approfondie et de la bonne mise en œuvre de cette.
Comment rapide est-ce?
Cette méthode élimine un niveau de commutateur ou de la consultation d'une table, que l'état est un droit pointeur vers une fonction que vous venez d'appel. Cependant, comme d'habitude, vous ne pouvez être certain de la vitesse réelle augmentation de la tester! Il devrait aider à la maintenance, trop, ce qui peut être important en grande-assez projet.
Très joli, mais pourriez-vous faire de ces E_*'s dans un
typedef enum
s'il vous plaît? (voir: stackoverflow.com/a/1102556/588561) Ce tire parti de ce que la vérification de type C a (certes, pas beaucoup) pour attraper plus d'erreurs. Ceci est particulièrement important lors du mélange de plusieurs machines d'état, où une simple réutilisation d'un nom d'événement à partir d'une machine à l'autre peut avoir de très bizarre, difficile à déboguer les conséquences.Une correction de ma part: plutôt que de typedef, vous pouvez envisager d'utiliser des structures avec des enums, voir stackoverflow.com/q/8597426/588561 pour l'explication. À l'aide de
struct A_state { enum A_state st; }; struct B_state { enum B_state st; }
etc. aide lorsque vous traitez avec plusieurs machines à états dans la même application, Ceci vous évite de mélanger les événements d'une machine d'état avec celles d'un autre, parce que leurs structures sont différentes, de type incompatible. Bien sûr, vous pouvez stocker d'autres variables d'état liées à une machine correspondant à la structure, trop.OriginalL'auteur squelart
Le meilleur moyen est largement subjective, mais d'une façon courante est d'utiliser une "table" approche vous permet de mapper des codes d'état (énumérations, ou quelque autre type intégral) à des pointeurs de fonction. La fonction renvoie votre prochain état et d'autres données associées et boucle jusqu'à ce que le terminal est atteint. Cela pourrait en fait être ce que vous décrivez comme votre approche ci-dessus.
OriginalL'auteur bobbymcr
C'est à peu près l'approche standard. Si vous êtes intéressés à l'étude d'un bien considéré comme la bibliothèque et la comparaison de détails, jetez un oeil à Ragel:
OriginalL'auteur ars
Instructions de commutation sont une bonne façon de commencer, mais ils ont tendance à être difficile lorsque le FSM s'agrandit.
Un couple (ou double) DONC des questions, avec beaucoup d'informations et d'idées:
OriginalL'auteur Michael Burr
J'ai utilisé ce modèle. Est-il typique de l'état de la machine modèle d'implémentation? (vérifiez la meilleure réponse).
Mais j'ai également ajouter des fonctionnalités
1. Des informations sur l'état antérieur.
2. Passage de paramètres
3. L'ajout d'événements externes comme le délai global et "resseting SM"
J'ai trouvé de l'état des machines un peu moins cryptique et maintenable.
De toute façon, je pense toujours que l'état des machines sont les plus difficiles et ennuyeux tâche de programmation.(J'ai eu jusqu'à présent)
OriginalL'auteur Luka Rahne
Une approche alternative est un tableau 2D qui décrit, pour chaque état/événement combinaison les actions à exécuter et à l'état suivant. Cela peut devenir plus compliqué à gérer quand vous avez besoin d'une transition à différents états en fonction de "circonstances", mais il peut être fait pour bien travailler. Vous avez un événement de reconnaissance de la fonction qui retourne le prochain événement, vous avez la table, où chaque entrée dans le tableau indique la fonction à appeler sur la réception de l'événement et l'état suivant - à moins que la fonction appelée remplace celui de l'état.
En fait la génération de code est fiddlier - il dépend de la façon dont le FSM est décrite dans la première place. Spotting double actions est souvent important. Souvent, vous pouvez compter sur "sparse matrix' techniques qui n'enregistrent pas de gestion d'erreur explicite: si l'entrée logiquement existe dans la matrice creuse, d'agir sur l'événement/état de l'information, mais si l'entrée n'existe pas de vous rabattre sur d'erreur approprié de reporting et de resynchronisation de code.
D'un tableau 2D de pointeurs vers des structures peuvent être passés dans un générique FSM fonction; le fait que vous écrivez un triple pointeur est assez pour vous faire attention à ce qui se passe. (J'ai écrit un de ceux de en Mars 1986 - je n'ai pas la source que sur le disque, même si j'ai encore l'impression du document qui la décrit.)
OriginalL'auteur Jonathan Leffler
Ont un coup d'oeil ici: http://code.google.com/p/fwprofile/
C'est une version open source (GNU GPLv3) de la machine d'état mis en œuvre
dans C. Le concept et la mise en œuvre est bien adapté à une utilisation dans
les applications critiques. Il y a des déploiements industriels
des applications.
OriginalL'auteur Vaclav Cechticky
J'utilise des pointeurs de fonction et un 2d (look-up table où j'utilise l'état pour un paramètre et l'événement comme les autres.
J'utilise excel (ou tout outil de feuille de calcul) pour mapper une fonction à chaque état/événement combinaison.
Lorsqu'un événement se produit, j'ai que ça, alors j'ai quelque chose qui ressemble à ceci
Cette méthode oblige essentiellement le développeur de considérer tous les événements possibles dans chaque état, et dans mon expérience, permet de déboguer un peu plus facile.
OriginalL'auteur Ryan B