|
Boost : |
From: Andreas Huber (ah2003_at_[hidden])
Date: 2004-05-25 04:58:04
Hi Johan,
> I've only read through the tutorial and glanced at the rationale, so bear
> with me if I've missed something out. I have not looked at the
> implementation. In brief it looks like some real good work has been invested
> into the development of the library! Some personal opinions though (of which
> I think some has been discussed otherwere in this thread):
>
> 1. No real support for runtime-defined fsm:s (yes, I've read the rationale).
> This is something that I personally _could_ live without, but would prefer
> not having to. I've definitely have had the need for (and implemented) a
> totally runtime-defined fsm. The problem would be how to implement this
> generically without the need for common interface classes ... hmmm.
> <speculation/>How about implementing two models within boost::fsm (dynamic +
> static model), or allow a hybrid approach?</speculation>
Runtime-defined FSMs are fundamentally different implementation-wise from
statically defined FSMs and IMHO the rationale clearly explains this. I
believe a hybrid approach with a common implementation would inevitably throw
away some of the advantages of statically defined FSMs. To retain these
advantages, you'd need to have two different implementations. Even worse, the
current interface is incompatible with dynamic FSMs, so a hybrid approach
would basically need two different interfaces.
So you end up with two mostly incompatible interfaces and two implementations
and that's why I think that dynamically defined FSMs should be tackled in a
separate library.
> 2. I'd prefer the states to be more loosely coupled (i.e. not having to know
> about other states at the same or higher levels, or the fsm itself). The fsm
> could take care of transitioning based on incoming events, current state and
> the abstract "result" of the event[*]. This way the state transitioning
> could be extended/changed without rewriting the states themselves.
Umm, I don't fully understand what you're getting at. Currently, a state only
has to "know" its outer states and all the states it transitions to. With
custom_reactions you can losen the latter relationships by shoving these
dependencies into other translation units. So, in a way you can already change
some aspects of a state without "rewriting" it.
> 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 guess by now my ignorance
> of the implementation shines through -> are enclosing states actually state
> machines already in boost::fsm?
Although states with inner states can be seen as separate state machines, they
are not implemented this way, mainly for performance reasons.
> 3. The entering/exiting of a state is modeled by the
> construction/destruction of a state object (see details in subsections).
>
> 3.1 Entering/exiting a state should be decoupled from creating/destroying
> the state objects themselves. I can see the simplicity in creating the
> states when they are entered etc, but for me states live continuously within
> a fsm; they are just entered/leaved at certain points in time.
So you would still have objects for states but you'd create them when the
state machine is created, right? This is contrary to the scalabilty
requirements as a state machine would have to know exactly which states belong
to it. I.e. you are forced to implement the whole state machine in a single
translation unit.
> And - if they
> happen to be active states (i.e. run by a thread or running a worker thread
> themselves) they might need to perform background activities even when they
> are inactive.
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.
> 3.2. The initialization of a state could be potentially expensive; needing
> to initialize (construct) a state each time it is entered could result in
> intolerable performance.
Yes, boost::fsm is definitly not for applications that absolutely need top-
notch dispatch and transition performance. I've personally never seen an
application where boost::fsm would be too slow (see Speed versus scalability
tradeoffs in the rationale). But, I've seen applications with scalability
problems during state machine development (huge amounts of generated code
resulting in long compilation times, recompilation of the whole state machine
every time a small detail is changed, etc.). That's why boost::fsm focuses on
good scalability and trades some of the theoretically possible speed for it. I
realize that this might be the wrong decision for a few applications but I
expect that a wide range of applications will perform reasonably with
boost::fsm.
I have some feedback from an independent real world project that seems to
confirm my view. Sure, this is only one project but it might nevertheless
remove some doubts. I'll ask whether he is willing to share his experience
with boosters.
(consider a state needing to setup a TCP
> connection). This could be handled in the current fsm implentation (I
> believe) by keeping such things in the fsm or enclosing state - but there's
> that coupling again.
You lost me here.
>
> 3.3 I prefer (to the utmost extent) that initialization/construction is
> performed once, which should be during the application initialization.
Are you suggesting that multiple state machine objects should use the same
state objects?
> Once
> done, I'd like to know that my state objects (in this case) are constructed
> and that the will remain so for the rest of the execution; no memory
> allocation errors;
If you want to avoid memory allocation errors that's no problem, just
customize memory management and preallocate as much as will be needed by your
application.
> no socket creation errors; ... etc .. during runtime
> [basically the same as 3.2 above]. (aka "do or die").
No problem either, just allocate your socket first thing in an outermost state
and never leave that state unless the state machine is terminated.
> 4. Built-in support for active states would be great. Perhaps you've been
> reading Miro Samek's great articles in CUJ (if not, please do so). Providing
> at least some rudimentary (but expandable) support for active states would
> be ... great (am I reapeating myself or what).
I'm not entirely sure what you mean with active state. Do you mean UML do-
activities? If yes, then you can already implement these with a thread that is
started in the entry action and cancelled (!) in the exit action of a
particular state.
>
> 5. If the dynamic stuff's never going to happen; perhaps provide an example
> on how to implement a runtime-defined fsm on top of boost::fsm (you briefly
> mention the possibility in the rationale) [related to 1].
Huh? I guess I was dreaming when I wrote that. Where do I mention this? I
don't see any way how a dynamic FSM could be implemented in terms of
boost::fsm.
Regards,
Andreas
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk