Boost logo

Boost :

From: Johan Nilsson (johan.nilsson_at_[hidden])
Date: 2004-05-25 06:55:00


Andreas,

"Andreas Huber" <ah2003_at_[hidden]> wrote in message
news:loom.20040525T102414-987_at_post.gmane.org...
> 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.

boost::fsm::static and boost::fsm::dynamic ? ;-)

>
> > 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.

That's mainly what I was getting at.

 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.

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).

>
> > 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).

>
> > 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?

No, before.

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.

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>)

>
> > 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.

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 (and - as I mention
below - I'd obviously prefer not having to re-create the connection upon
each state entry).

>
> > 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.

I just meant that the state is dependent on its "container" to maintain
non-volatile data.

>
> >
> > 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.

Well, memory allocation problems are rarely a problem nowadays; it was just
an example.

>
> > 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.

Isn't that quite a restriction? I do like the 'context' stuff, but in a
complex statemachine the context could get bloated with unrelated
functionality.

>
> > 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?

Oops, sorry. I realize the term 'active state' could easily be a source of
confusion. I'm not referring to the currently active state in the fsm; I
mean a state that performs its "own" activity when it is the fsm:s active
state (i.e. even when not executing in the context of a call event or
signal).

I just looked up the term do-activity and it seems to model the concept
rather nicely.

 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.

Again, that's quite a heavy-weight solution. How about implementing the
do-activity with a worker thread in the fsm itself (requires cooperation
from within the active state, of course).

>
> >
> > 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.
>

--- rationale excerpt ---
Why not use a dynamically configurable FSM library for all state machines?
...
It is for these reasons, that boost::fsm was built from ground up to not
support dynamic configurability. However, this does not mean that it's
impossible to dynamically shape a machine implemented with this library.
...
--- end rationale excerpt ---

Or do I misinterpret the meaning of the text?

// Johan


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk