Boost MSM - Ways to send info out from state machine to outside world
Hi, I wanted to know what are different ways to send info from state machine to outside world. I am planning to use MSM in my project to represent connection between local computer and remote computer. This connection will be used as a channel to send data over to remote device. There can be >1 channels existing between local computer and the remote device. There will be a controller sitting at local computer monitoring all these channels. The data will be sent over connection that is idle/free at that point of time. Whenever the connection, i.e. FSM, is done sending the data, it will let the controller (which resides outside of the FSM) know that it is done sending the data and the controller will then send next lot of data over that connection. There can be 2 ways of achieving this: 1. Controller polling all the connections and knowing what "state" the FSM is in.(In this case, the outer world will need to know the current state of the state machine) 2. The FSM will proactively let the controller know that it is done with sending data. (In this case the FSM will have to send data to outside world). I would like to know about ways to implement both the cases (i.e knowing status/current state of the FSM and sending info from FSM). I would also like to know what are different ways to interact with (both to and from) FSM in general, apart from sending events. Thanks! -- View this message in context: http://boost.2283326.n4.nabble.com/Boost-MSM-Ways-to-send-info-out-from-stat... Sent from the Boost - Users mailing list archive at Nabble.com.
Hi,
I wanted to know what are different ways to send info from state machine to outside world. I am planning to use MSM in my project to represent connection between local computer and remote computer. This connection will be used as a channel to send data over to remote device. There can be >1 channels existing between local computer and the remote device. There will be a controller sitting at local computer monitoring all these channels. The data will be sent over connection that is idle/free at that point of time. Whenever the connection, i.e. FSM, is done sending the data, it will let the controller (which resides outside of the FSM) know that it is done sending the data and the controller will then send next lot of data over that connection. There can be 2 ways of achieving this: 1. Controller polling all the connections and knowing what "state" the FSM is in.(In this case, the outer world will need to know the current state of the state machine) 2. The FSM will proactively let the controller know that it is done with sending data. (In this case the FSM will have to send data to outside world). I would like to know about ways to implement both the cases (i.e knowing status/current state of the FSM and sending info from FSM). I would also like to know what are different ways to interact with (both to and from) FSM in general, apart from sending events.
Thanks!
Hi, I personally use mostly 2. but 1. is useful if you need to do something at some regular interval. To 1: - current_state / get_state_by_id will get you a base class of all states if you define one. - better is to use flags (http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch03s02.html#d0e1032) to know if your fsm fulfills some property (is in one or more states which define these flags). It's a bit like knowing in which state you are but more general. This one is my favorite. - you can use a visitor (http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch03s05.html#d0e2333) to let the current state "do" something. To 2: This shouts for a transition action (http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/ch03s03.html#d0e1260). An action is a functor or a function which is called when a transition fires. There is no rule written in marble, but I suggest you stick to 2. until you cannot do otherwise, it will make your fsm much more useful and readable. Plus, it mixes very well with boost.asio (I do it quite a bit myself). Every callback from asio generates some event, to which the fsm reacts by changing state and calling another action, which triggers another asio task, etc. For example, a HTTP client (http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/http/client...): - fsm starts - when asked, fsm calls async_resolve - handle_resolve generates an event which triggers a transition - the transition action calls async_connect - handle_connect generates an event which triggers a transition - the transition action sends data by calling async_write etc. etc. Add some events and actions for error handling and you get a pretty complete communication handling in a fsm. To your last question, interact with a fsm, well, it's a class so you can add whatever methods or attributes you might need. HTH, Christophe
Hi, I had one more question about the lifetime of the FSM. When does the state machine die? I was expecting that the state machine has to be explicitly killed (similar to fsm's start() method). But from whatever I have figured out, I think the state machine dies if it is in a state and no event occurs. If that is true, what will be an elegant way to "wait" inside a state till some event occurs (i.e. keeping FSM alive)? I came up with 2 ways: 1. Have following transition from the waiting state: Row < state_waiting , none, state_waiting , none, none> and keep on calling process_event(none()) This however causes the entering the state again and again and gives me segmentation fault ultimately. 2. Have following transition: Row < state_waiting, none, state_waiting, none, Gc_always_false> where guard condition Gc_always_false returns false, prohibiting the transition but still keeping the state machine alive. Can you please tell me if the 2nd option is correct and if there is a better way to sit idle in one state and keep the machine alive. Thanks! -- View this message in context: http://boost.2283326.n4.nabble.com/Boost-MSM-Ways-to-send-info-out-from-stat... Sent from the Boost - Users mailing list archive at Nabble.com.
Hi,
I had one more question about the lifetime of the FSM. When does the state machine die? I was expecting that the state machine has to be explicitly killed (similar to fsm's start() method). But from whatever I have figured out, I think the state machine dies if it is in a state and no event occurs.
No, what gave you this idea? I'm afraid you're mixing 2 concepts. The lifecycle of a state machine is the same as any other class. Created on the stack, it is destroyed by stack unwinding, created on the heap, by delete. The second concept is what is called run-to-completion. A state machine processes an event to the end (meaning, guard, exit, transition action, entry) then does nothing until another event is processed. True, there are state machine libraries running constantly in a thread, but this eats your cycles faster than a wolf a herd of sheeps and causes more race conditions than the upcoming Oktoberfest will produce drunken tourists sleeping on the pavement on my way home ;-) So, no, msm does not do this. The method start() is simply an optimization allowing you to delay the first call to on_entry until you really want it.
If that is true, what will be an elegant way to "wait" inside a state till some event occurs (i.e. keeping FSM alive)? I came up with 2 ways:
1. Have following transition from the waiting state: Row < state_waiting , none, state_waiting , none, none> and keep on calling process_event(none()) This however causes the entering the state again and again and gives me segmentation fault ultimately.
Yes, stack overflow. Not something you want.
2. Have following transition: Row < state_waiting, none, state_waiting, none, Gc_always_false> where guard condition Gc_always_false returns false, prohibiting the transition but still keeping the state machine alive.
Can you please tell me if the 2nd option is correct and if there is a better way to sit idle in one state and keep the machine alive.
If you want to keep your processor busy, sure, but I won't recommend it ;-) Seriously, a state machine is event-triggered and does nothing until a next event is fired. It's a purely reactive system. What are you trying to achieve? HTH, Christophe
Christophe Henry-3 wrote:
2. Have following transition: Row < state_waiting, none, state_waiting, none, Gc_always_false> where guard condition Gc_always_false returns false, prohibiting the transition but still keeping the state machine alive.
Can you please tell me if the 2nd option is correct and if there is a better way to sit idle in one state and keep the machine alive.
If you want to keep your processor busy, sure, but I won't recommend it ;-) Seriously, a state machine is event-triggered and does nothing until a next event is fired. It's a purely reactive system. What are you trying to achieve?
I was under the impression that if the FSM runs out of events it dies and so one needs to keep feeding it events (be it none()) to keep the machine alive. In my case, I can think of at least two scenarios where my machine will be sitting idle: 1. While setting up connection, till it gets response from the remote device 2.After sending its share of data, till it receives new lot from the controller. Since I was under the impression that I have to keep calling an event to keep the machine alive, I was looking for a mechanism that will let me call an event but /not/ change the state and /not/ keep reentering the same state again and again, causing seg fault.
From what you are saying, I will assume that if the state machine enters waiting state (or any other state for that matter) and no event occurs, it will stay in the same state forever. Also, I will assume that the state machine will die whenever it goes out of scope (if its a stack variable) or is explicitly deleted (if created on heap).
Christophe Henry-3 wrote:
True, there are state machine libraries running constantly in a thread, but this eats your cycles faster than a wolf a herd of sheeps and causes more race conditions than the upcoming Oktoberfest will produce drunken tourists sleeping on the pavement on my way home ;-)
Btw those analogies were hilarious! Thanks for the help! -- View this message in context: http://boost.2283326.n4.nabble.com/Boost-MSM-Ways-to-send-info-out-from-stat... Sent from the Boost - Users mailing list archive at Nabble.com.
One more question. So how do the guard conditions work? Does the state machine keep checking periodically if the guard condition is satisfied or not and make transition if the condition is met or it checks for the condition only when an event occurs? Thanks! -- View this message in context: http://boost.2283326.n4.nabble.com/Boost-MSM-Ways-to-send-info-out-from-stat... Sent from the Boost - Users mailing list archive at Nabble.com.
One more question. So how do the guard conditions work? Does the state machine keep checking periodically if the guard condition is satisfied or not and make transition if the condition is met or it checks for the condition only when an event occurs?
Thanks!
No. This would be again my metaphors about eating your cycles. It would also require an extra thread and this would be the race condition stuff. The guards are evaluated when you process an event. When you call process_event(event()), the state machine does: - check the guard. If true: - call the exit action - call the transition action - call the entry action - else: check if another transition is possible. If yes, repeat, otherwise stop. Then it does nothing again. HTH, Christophe
Christophe Henry wrote:
2. Have following transition: Row < state_waiting, none, state_waiting, none, Gc_always_false> where guard condition Gc_always_false returns false, prohibiting the transition but still keeping the state machine alive.
Can you please tell me if the 2nd option is correct and if there is a better way to sit idle in one state and keep the machine alive.
If you want to keep your processor busy, sure, but I won't recommend it ;-) Seriously, a state machine is event-triggered and does nothing until a next event is fired. It's a purely reactive system. What are you trying to achieve?
I was under the impression that if the FSM runs out of events it dies and so one needs to keep feeding it events (be it none()) to keep the machine alive. In my case, I can think of at least two scenarios where my machine will be sitting idle: 1. While setting up connection, till it gets response from the remote device 2.After sending its share of data, till it receives new lot from the controller. Since I was under the impression that I have to keep calling an event to keep the machine alive, I was looking for a mechanism that will let me call an event but /not/ change the state and /not/ keep reentering the same state again and again, causing seg fault.
From what you are saying, I will assume that if the state machine enters waiting state (or any other state for that matter) and no event occurs, it will stay in the same state forever. Also, I will assume that the state machine will die whenever it goes out of scope (if its a stack variable) or is explicitly deleted (if created on heap).
The state machine will die only when destroyed (by going out of scope or being deleted). Until it happens, it does nothing. The only time it does something is when you process an event.
Christophe Henry wrote:
True, there are state machine libraries running constantly in a thread, but this eats your cycles faster than a wolf a herd of sheeps and causes more race conditions than the upcoming Oktoberfest will produce drunken tourists sleeping on the pavement on my way home ;-)
Btw those analogies were hilarious!
Thanks for the help!
:)
Understood (I guess! :-)). Thanks for the help! -- View this message in context: http://boost.2283326.n4.nabble.com/Boost-MSM-Ways-to-send-info-out-from-stat... Sent from the Boost - Users mailing list archive at Nabble.com.
participants (2)
-
Christophe Henry
-
gauravk