Boost logo

Boost :

From: Andreas Huber (ah2003_at_[hidden])
Date: 2003-06-01 16:47:36


Bohdan wrote:
> Hi Andreas,
>
> It is really nice to hear that FSM lib is ready for submission.
>
> Here are my comments :
>
> 1. Can you port your library to other compilers,
> at least for gcc ? I was trying to port older fersion
> of your lib to Borland, but code is too complicated
> to make it shortly.

Unfortunately, I don't have much experience with anything else than MS
compilers. I will try to port to gcc, but I'll probably need help for
not-so-conforming compilers like Borland.

> 2. I think that nice thing about state machine is
> that you can remove its actual states from interface.
> I mean : "is it conceptually good idea to pass initial
> inner state as a template parameter ?"

Hmmm, I never liked it that much myself but I was forced to design it this
way due to some constraints of an earlier design. Now that you mention it, I
think it should be possible to specify the inner initial state with the
initiate() function, which could be called as follows:

Pump.hpp:

class Pump : public fsm::state_machine< Pump >
{
  public:
    void Start();
};

Pump.cpp:

struct Idle : public fsm::simple_state< Idle, Pump >

void Pump::Start()
{
  initiate< Idle >(); // ***** here *****
}

Did you have something like this in mind?

> 3. Why we need state_machine class, wouldn't it
> better to have a single "state" class for
> both state & state_machine.
> IMO state_machine is just state, which can't be
> changed and which doesn't have outer state.
> Am i wrong ?

The state_machine and simple_state templates have quite differing interfaces
and implementation so I'm not sure what that would buy you. Of course, it
would be a simple matter to automatically make a state without an outer
state derive from state_machine behind the scenes but I believe that would
confuse people more than anything else. A state machine handles states and
queues events while a state is not much more than an identifier.

> 4. Is it possible to use inherited events?
> ex:
> class MouseEvent;
> class MouseUpEvent : public MouseEvent;
> class MouseDownEvent : public MouseEvent
>
> <code>
> bool react( MouseEvent const& event )
> {
> ...
> }
> </code>
>

No, not exactly as you are suggesting. Although you can derive events from
each other to write common code only once, you must always pass the most
derived type to the fsm::event class template:

template< class MostDerived >
class MouseEvent : public fsm::event< MostDerived >
{
  /* common mouse event code */
};

class MouseUpEvent : public MouseEvent< MouseUpEvent > {};
class MouseDownEvent : public MouseEvent< MouseDownEvent > {};

The best approximation of what you want to do is the following:

struct Idle : public fsm::simple_state< Idle, Whatever, mpl::list<
  fsm::custom_reaction< MouseUpEvent >,
  fsm::custom_reaction< MouseDownEvent > > >
{
  template< class MostDerived >
  fsm::result react( const MouseEvent< MostDerived > & ) { /* ... */ }
};

That is, you can write one react member function for all mouse events but
you have to explicitly mention all most derived classes in the reaction
list.

I did consider polymorphic events but I wasn't able to make double dispatch
work *automatically* (i.e. without requiring the user to write parts of the
dispatch code themselves).

I personally need polymorphic events only very rarely. Whenever I did, I was
always able to change event granularity so that the need would go away. In
your case that would mean to get rid of MouseUpEvent and MouseDownEvent
alltogether and add the information to MouseEvent:

struct MouseEvent : public fsm::event< MouseEvent >
{
  enum ButtonMode { Up, Down };
  ButtonMode mode_;
};

In reactions where you need to discriminate on Up/Down you simply use a
guard.

Does the library/code generator you're currently using work with
polymorphic events? Is not having polymorphic events a showstopper for you?
If yes, I would be interested in a as-real-world-as-possible example.

> 5. Is it possible to inherit state machines:
> some states replaced, some removed ... ?

Unfortunately not. I believe that is only practicable with a code generator.

> 6. Is there any way to get rid of "Acyclic Visitor".
> Some dispatch policies ... ?
> Hope this question isn't too annoying :)

boost::fsm no longer uses acyclic visitor! The current double dispatch
implementation (which was inspired by Aleksey's fsm lib) uses one virtual
call followed by a linear search for a suitable reaction, using one RTTI
comparison per visited reaction. Although you cannot change the double
dispatch implementation itself, you can change one aspect of it, i.e. RTTI.
The BitMachine example shows how to replace native C++ RTTI with integers.

I think only acyclic visitor and the above implementation fit the
scalability requirements as documented in the rationale. While it should be
possible to abstract them in a policy I think that effort would be a waste
of time because the current approach is better in *all* aspects!

Thanks for your feedback!

Regards,

Andreas


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