
Hello Andreas, Friday, December 22, 2006, 10:23:50 PM, you wrote:
Andrey Semashev wrote:
As soon as an FSM needs to be able to process events of arbitrary types you usually need to allocate these events on the free store anyway, also allocating the states there just doubles the runtime needed for new/delete. Sure, you can save all those free store allocations when your FSMs only need to deal with one type of event and state but for many applications this simply is not flexible enough.
I can't quite agree with you. As it comes from my experience, one of the most frequent FSM use cases is when the state machine implements some public interface. In this case interface method calls have to be translated into events that may be accepted by FSM. And most likely these events will be on the stack.
Fair enough, my experience mainly comes from applications where an FSM either runs in its own thread or is fed by some kind of scheduler. As I've explained in the performance document, in such a scenario the inter-thread synchronization costs are usually far higher than cost of anything Boost.Statechart does.
That's right, threading costs overcome the FSM infrastructure costs by far. I was comparing the two libraries both in single thread context.
As for states' allocation and deallocation, there may be other issues with it, besides of performance loss. I'm not quite sure you have read our discussion with Alexander Nasonov in this thread, where I pointed out that the fact that the state is deleted when being left may be inconvenient if the state has its local data. If the state is visited again all these data are lost.
Right, in my experience this is the behavior that is most commonly wanted. IIUC, what you want is something like the currently supported history but with the added feature that all local variables are also restored upon entry of the state. Such a feature has been suggested before but I've so far not found a satisfying way to implement it. IMO, you definitely need both options and sometimes a state even contains multiple variables with different needs of resetting/reconstitution.
Agreed, that's why I decided not to delete states during transitions. If some variables need to be reset when the state is being left, a user may implement such logic in the appropriate handler function. Just a thought of similar functionality support in Statechart. If there was an additional optional template parameter in the "state" or "simple_state" class template that would have a type of the state's context which lifetime would last from the first entrance into the state until the whole state machine destruction (let's call it a static state context), then a reference to the context might have been passed to the state's constructor. For example: // This will be the static context struct State1Ctx { int n; }; struct State1 : public sc::simple_state< State1, OuterState, State1Ctx > { // This reference will hold the context State1Ctx& static_ctx_; // In ctor we receive a reference to the static context. // No matter how many times we enter the state, // we get the reference to the same object here State1(State1Ctx& ctx) : static_ctx_(ctx) { } }; Or, alternatively, the static_ctx_ reference may even be in the "simple_state" class itself. It may be accessible via some public method.
And moving these data to an outer state or even the to the state machine class makes it exposed to other states that shouldn't have had access to it.
Correct, it's not an optimal solution, but it is in my experience not needed very often.
I wouldn't say it's vital for a user. It's just a question of quality of user's code that uses the library. But, IMHO, the FSM concept should help to distinguish and separate states of an object.
Additionally as the data amount and states number raises the code of these data-holding classes gets more messy.
You've lost me here: Which data-holding classes? In Boost.Statechart there are only states.
By "data-holding classes" I meant collectively states and the state machine classes that can hold data of inner states that we were discussing above. I was saying that as the amount of states grows so does the amount of data. And if it is stored in some outer state, the state becomes overweightened and messy. To my mind this issue should be of special concern since Statechart is more targeted to creation of bigger state machines.
- I can see no way to return a value from a Boost.Statechart's machine except by passing a reference or a pointer in the event.
Correct. How do you return a value? With boost::any?
Not necessarily. The return type is passed in a state machine's template parameter and may be any type, including boost::any. This feature is optional, so by default this type is "void" (IOW, the FSM returns nothing).
I see that something like this could useful for the use-case you described. It's not supported in my library because for asynchronous machines the return value would be lost anyway and even for synchronous machines it would be meaningless when a machine processes multiple events in one call as a result of the posting of an internal event. It is probably for these reasons that the UML standard does not allow a return value.
I see. Probably, you're right, there's little use of this functionality in cases you describe.
BTW, is there any way to make Boost.Statechart's machine not compiling if it doesn't expect some particular event type? IOW, to force the machine to support all event types being passed to it?
No, as that would require the implementation of the whole machine in one TU. IMO, the ability to compile parts of a large machine separately is more important in practice.
Ah, that's right. Modularity takes its toll. -- Best regards, Andrey mailto:andysem@mail.ru