|
Boost : |
From: Andrey Semashev (andysem_at_[hidden])
Date: 2006-12-22 18:50:54
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_at_[hidden]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk