
"Andreas Huber" <ah2003@gmx.net> wrote in message news:loom.20040525T161541-653@post.gmane.org...
Johan Nilsson <johan.nilsson <at> esrange.ssc.se> writes:
boost::fsm::static and boost::fsm::dynamic ?
Or boost::static_fsm and boost::dynamic_fsm...
[snip]
Sorry, "rewriting" was entirely incorrect; I referred to modifying the source code when a reaction (correct terminology?) should result in a transition to a newly implemented state (i.e. one not originally defined).
I guess we agree that you have to modify some code somewhere to achieve
behavior change. What's so bad about changing the code of the state where
Even better. this the
new transition originates? I think this is superior to having a global transition table. Such a global table inevitably becomes a change hotspot in large FSMs and leads to frequent recompilations.
Are we convinced that the only thing we're discussing now is static FSMs? If so, you are correct and I believe you've made a correct design decision in this particular respect.
[snip]
Exception: outer states should have some knowledge about inner states (they might be considered state-machines themselves).
I don't see what that would buy you. I think it is a bad idea to have outer states know exactly what inner states they contain. This would make it close to impossible to spread machines over multiple translation units, which I consider a key feature of my library.
I didn't intend to imply that states should _exactly_ know their inner states (i.e actual types). I was thinking more in terms of the implementation of a superstate as an fsm itself (and, more specifically I guess, dynamic fsm:s).
Ok, but I still don't understand your question/suggestion/proposal. Could you please expand?
It's neither; we're comparing apples and pears (well, that might be a swedish idiom only ;-). If a static FSM would have complete control over all transitions, analogous to the dynamic example I provided below, the static FSM would need to know all inner states. If a dynamic FSM would have complete control over all transition it doesn't need to know the exact type of all inner states. Am I correct?
[snip]
So you would still have objects for states but you'd create them when
the
state machine is created, right?
No, before.
When before? At program startup?
Perhaps - perhaps not. I've got my mind set up for dynamic FSMs so I guess this is rather irrelevant for the discussion.
[snip]
No, only if statically defined. I was thinking in runtime-terms again, perhaps:
// // pseudo-code (no, I didn't think thoroughly before writing this) // from_state_id = fsm.add_state(<some-state>) to_state_id = fsm.add_state(<another-state>) fsm.add_transition(from_state_id, <on-event>, <event-result>,
to_state_id)
fsm.add_transition_to_self(from_state_id, <another-event>, <another-event-result>)
Yes, this is incompatible with static FSMs...
Obviously ;-)
[snip]
I've never heard about such a state machine feature. UML has do-activities that are associated with a certain state. When the state is left the do- activity is aborted.
I guess it's not in the formal definition of state machines. I'll try to give an example; suppose one state is responsible for updating the status of a remote entity via TCP when active; but the remote entity requires a periodic keep-alive so as not to close the connection
Why not create the thread in an outer state or even in the state machine constructor and keep it alive for the whole lifetime of the state machine? If the thread needs to be alive longer than a certain state does I would consider it a design error to make it a member of the state.
See comments below.
[snip]
connection). This could be handled in the current fsm implentation (I believe) by keeping such things in the fsm or enclosing state - but
(consider a state needing to setup a TCP there's
that coupling again.
You lost me here.
I just meant that the state is dependent on its "container" to maintain non-volatile data.
Yes, what's so bad about that? An inner state always depends on the behavior implemented by its outer state. Just like a derived class always depends on the implementation of its base class.
For me, an inner state "is-not-a" outer state (regardless of the name 'superstate' in the UML docs). The outer state <-> inner state relation feels more analogous to an association (or perhaps an aggregation). So the comparison to base and derived feels a bit out of hand. That's why I don't like the dependency on the "container". Two way associations generally bring with them too much coupling, IMHO. Let me make an alternate suggestion: The states needing 'persistent' data (or functionality, such in the admittedly convoluted TCP example above) would tell the state machine to maintain a special context object for them - for the entire lifetime of the FSM. This context object could be of any class -> but should _not_ be the fsm itself or an outer state. The context object could inherit from a specific base just so that the fsm could store them conveniently. The type of the context object could be specified as a template parameter to the e.g. simple_state<> template. I'll try to outline an example, just to give you an idea (I won't consider the exact steps needed to actually implement this): namespace fsm { struct no_context : fsm::context<no_context>{}; } struct my_state_context : public fsm::context<my_state_context, ...> { }; struct my_state : public fsm::simple_state< my_state, ..., my_state_context /* defaults to fsm::no_context */
{ }; Access to the context should be made easy by providing the 'context()' method in simple state, now returning a reference to the FSMs only instance of the context -> implemented in simple_state. The 'context' method should be unavailable if the context template argument equals no_context; perhaps doable through PTS. What would also be needed is the ability for several (closely related) states to share the same context, but _still_ without the need for the context to be the outer state or fsm - needs some consideration on how to implement this. As you see I really haven't concrete examples on how to implement this - but given this or similar implementation I could leave out the requirements for the actual state objects to remain live for the lifetime of the FSM itself. Now I could even make the context object an "active" object (i.e. run by a private thread). We'd still have the benefits of your basic FSM design; we'd have looser coupling between outer, inner states and the FSM. I'll leave the rest of the discussion for now, as most of it relates to dynamic FSMs (perhaps with the exception for out-of-the-box support for do-activities, which I'd like to have included). What do you say? // Johan