
Tim Milward wrote:
Johan Nilsson wrote:
1. For a state, is it possible to specify a method that will be called when an event with no defined handlers is received?
Interesting question. Can all events inherit from a common base class, to which a state could define a (default) reaction, and override this with reactions to specific event sub-classes?
Should be possible from my point of view. Not sure how the framework would handle that even though it sounds reasonable. It's a bit limiting though, and should be possible have support for in the library. I'd figure it's a pretty common requirement to be able to take actions (log a warning or similar) when an unexpected event is received.
2. Is is somehow possible to reuse state definitions as substates of different "higher-level" states?
In boost/libs/statechart/doc/tutorial.html#TransitionActions it says, "With Boost.Statechart, a transition action can be a member of any common outer context" and goes on to give some examples. If I've understood your question correctly then the answer is "Yes".
Actually, I'm inclined to say "No" considering the following (partially duplicated from your part later in the posting): Top Remote Idle Executing Local Idle Executing This I cannot do, right? Idle and Executing would ideally be the same, but as they are statically associated with their outer states (and vice versa) it doesn't look like it's possible.
- I've got an application that can be either in remote or locally controlled mode (this is the highest-level states). - Certain events are allowed both in remote and local, while some are not. As an example, the "CommandEvent" event should be handled both in remote and local - resulting in the "ExecutingCommandState" being entered. - I'd like to be able to reuse the definition of ExecutingCommandState regardless of the enclosing state being Remote or Local - Possible?
Could you implement this with orthogonal regions?
Top Remote Local ------ Idle Executing
Here the top state contains two orthogonal regions separated by a dashed line.
Sorry for my ignorance, but what then happens if there would be an additional substate, that should only be possible when in e.g. the Remote state.
The only problem here is that actions (in transitions from say Idle) that need to be different depending on whether it's in Remote or Local gain conditional logic. (If that's all Remote and Local are used for they could just be replaced by a bool member of Top.) If you had
Top Remote RIdle RExecuting Local LIdle LExecuting
you'd avoid this, at the expense of possibly repeating code in the (only slightly different) actions of a transition originating from either RIdle or LIdle. This common code could perhaps be extracted into a method belonging to the shared super-state, Top.
This is more similar to what I've got. There isn't really any other code duplication that having to define the e.g. RIdle, LIdle, RExecuting, LExecuting, as the state machine itself holds a reference to the domain object responsible for executing the actions. Within the different states I simply get this object using context<StateMachine> and delegate - so the state machine is in this case only used for discriminating the disallowed events according to the current state. If I had lots of different actions that could be performed this would result in a very bloated interface for the domain object, but in this case it's not a problem - I can keep the interface down to 3-4 methods.
This sounds like a similar problem to the one I face. Where are you planning to execute the command? In my application the commands take a long time, so are not suitable for implementing as an action.
I'm planning to execute the command(s) in context of the react(...) method calls. Some of them do take a pretty long time to execute, but as the intention is to only accept one active command at a time it doesn't really matter (this isn't ideal though, see below).
UML provides "Do Activities" that can be used for this purpose. The statechart docs suggest simulating this "with a separate thread that is started in the entry action and canceled (!) in the exit action of a particular state". I quite like that approach.
I considered executing the commands in a worker thread similar to that approach; when receiving a command the FSM would enter the ExecutingCommand state, kick off a new thread (or using a previously existing worker thread) to execute the command. The problem I ran into that I wanted the command-executing thread _itself_ being able to signal the completion of the command (and thus trigger exiting the ExecutingCommand state to the previous state). It should never be possible to exit the state unless the command has run to an end, e.g. by unconditionally joining the worker thread in the state's destructor. I couldn't really find a clean, thread-safe way to implement this. Did you actually try to implement anything like this? Thanks // Johan