2010-10-18 2 views
1

J'ai remarqué que les messages envoyés au pid d'un processus gen_fsm sont mis en correspondance dans les rappels d'état en tant qu'événements. Est-ce juste accidentel ou puis-je me fier à cette fonctionnalité?Puis-je gérer un message reçu dans les rappels d'état gen_fsm?

Normalement, je m'attendais à ce que les messages généraux envoyés à un gen_fsm apparaissent dans le rappel handle_info/3 et je pensais que je devais le renvoyer en utilisant gen_fsm: send_event. Est-ce que gen_fsm essaie de faire correspondre le message d'abord avec le rappel d'état, puis avec le rappel handle_info/3? Ou seulement s'il ne correspond pas à une clause de rappel d'état?

Cependant quand je l'essaye mon message semble être traité deux fois selon la sortie de débogage. Donc, fondamentalement, la question peut également être posée comme: comment gérer correctement les messages reçus en tant qu'événements dans les fonctions d'état de gen_fsm?


Précision: que certains des événements se produisent en obtenant les messages transmis devraient être pris en considération donnée à cette question.

Je suis conscient que dans de nombreux cas, son nettoyeur rend le protocole visible en utilisant des appels de fonction dans le fsm seulement. Je ne suis pas sûr si cela améliorerait le cadre actuel où le gen_fsm mentionné doit s'intégrer: Diverses piles de protocoles où chaque couche appelle une fonction connect() pour attacher (et parfois démarrer) la couche inférieure. Les paquets sont envoyés aux couches inférieures ba appelant une fonction (envoi) et reçus par receive un message. Tout comme gen_tcp. En regardant le code pour gen_fsm, j'ai déjà compris que les messages généraux ne sont transmis qu'à handle_info, donc seule la question reste d'appeler la fonction state directement depuis le callback handle_info/3 ou de renvoyer gen_fsm: send_event.

+0

Est-ce que je vous ai bien compris ici, utilisez-vous gen_fsm uniquement pour une partie de la pile de protocoles et pas tout? Si oui, pourquoi? Pourquoi ne pas avoir implémenté la totalité de la partie Erlang de la même manière? Cela vous permettra d'être cohérent dans la façon dont les messages sont envoyés et reçus. – rvirding

+0

Je désactive systématiquement les messages {ok, Pid} = connect(), send (Pid, Data) et {receive, Data}. Je suis donc cohérent dans l'API des différents modules de la pile. Où je ne suis pas cohérent est le traitement de recevoir et envoyer actuellement. –

+0

Mais il y a beaucoup de code préexistant utilisant ce paradigme, c'est donc un effort pour tout changer. Raison de ne pas utiliser gen_fsm pour toutes les parties de la pile est que ses protocoles en fait très divers (protocoles de bus automobile) multiplexés sur USB. Ainsi, les parties de la pile varient entre gen_server, simple ad/hoc server et les filtres d'encodage/décodage sans état et gen_fsm bien sûr. –

Répondre

1

messages généraux sont traités par le rappel handle_info, sauf si vous avez quelque chose comme ceci dans votre code:

handle_info (Info, StateName, StateData) -> MODULE: StateName (Info, StateData).

Ce qui évite de renvoyer, mais je ne le recommande pas, ni ne le renvoie.

La livraison d'événements exclusivement au moyen d'appels d'API encapsulant send_event/sync_send_event/send_all_state_event/sync_send_all_state_event rend le protocole explicite. Ce qui est une bonne chose, car il est plus facile de comprendre, de maintenir et de documenter avec edoc.

+0

Le gen_fsm doit pour l'instant s'adapter à une architecture donnée de piles de protocoles construites selon le modèle: les niveaux inférieurs sont connectés par des niveaux plus élevés les paquets sont envoyés() mais sont reçus par l'envoi de messages aux niveaux supérieurs. Similaire comment gen_tcp gère les connexions. Donc soit je change toute la pile de code pour passer des callbacks au lieu de messages pour l'amont, ce que je préfère pas actuellement ou je dois gérer ces messages. –

+0

Appelez directement - c'est plus rapide. En outre, en cas de réexpédition si l'API est utilisée avec le passage de message, vous n'avez pas de garantie "livraison séquentielle d'une source". – probsolver

+0

Merci! Je l'ai déjà implémenté comme appel de fonction direct et il s'intègre parfaitement avec le reste du code. Et cela fonctionne aussi comme une brise. –

Questions connexes