Boost logo

Boost Users :

Subject: Re: [Boost-users] [statechart] Several questions
From: Andreas Huber (ahd6974-spamboostorgtrap_at_[hidden])
Date: 2009-05-05 08:25:29


Hi Michael

> 1. Is there a clean way to seperate the definition of a state from the
> definition of its initial inner state? Say we have
> // StatePlayGame.h
> #include "MyStateMachine.h"
> class MyStateMachine;
> class StatePlayGame : public boost::statechart::state<StatePlayGame,
> MyStateMachine, StateGameStartup>
> {
> //...
> };
> // StateGameStartup.h
> #include "StatePlayGame.h"
> class StateGameStartup : public boost::statechart::state<StateGameStartup,
> StatePlayGame>
> {
> //...
> };
> It appears that any translation unit that includes StatePlayGame.h also
> requires StateGameStartup.h in order to compile - obviously a less than
> ideal situation.

The implementation of a state and its inner initial state must always reside
in the same TU. There's no generally working way around that. However, you
can make the inner initial state just a dummy state that ...

1. posts a dummy event in its constructor, and
2. has a custom reaction that reacts to said event, and
3. defers all other events

// StatePlayGame.h:
// Includes omitted

struct EvDummy : sc::event< EvDummy > {};

struct Dummy;
struct StatePlayGame :
  sc::simple_state< StatePlayGame, MyStateMachine, Dummy > {};

struct Dummy : sc::state<Dummy, StatePlayGame >
{
  public:
    typedef mpl::list<
      sc::custom_reaction< EvDummy >,
      sc::deferral< sc::event_base > // Save possibly already pending events
> reactions;

    Dummy( my_context ctx ) : my_base( ctx )
    {
      post_event(new EvDummy());
    }

    sc::result react( const EvDummy & ); // Only declared here
};

// Dummy.cpp
// Includes & forward declarations omitted

sc::result Dummy::react( const EvDummy & )
{
  return transit<StateGameStartup>();
}

> 2. Is it possible to pass parameters to a state's constructor?

No, but that is a pretty popular request. I did consider to allow for state
constructors that could accept the triggering event as parameter. One
problem is that the same state can be entered as a result of several
different events, so you could only accept a base type and type-safety is
therefore wrecked. One might want to pass the arguments to transit<> but
that would preclude the entering of the state as a side effect of
state_machine::initiate.

> Going
> with
> the little example above let's say that StateGameStartup asks the player
> how
> many enemies he wants to fight, and then transitions to StateGameRunning,
> which needs that number. Can it be passed by StateGameRunning's ctor or
> is
> it just required that states can only share information via their context?

In this case I would store said number in StatePlayGame, assuming that
StateGameRunning is a substate of StatePlayGame. If the number of enemies is
passed in as an event carrying parameters then you could simply define a
transition from StateGameStartup to StateGameRunning, with a transition
action that stores the number in StatePlayGame.

HTH,

-- 
Andreas Huber
When replying by private email, please remove the words spam and trap
from the address shown in the header. 

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net