Boost logo

Boost Users :

Subject: Re: [Boost-users] [MSM] test if state machine is in a given state /const get_state
From: Christophe Henry (christophe.j.henry_at_[hidden])
Date: 2011-03-01 16:51:39


Hi Jan,

> i am working with the Boost 1.45 Meta State Machine, using both
> orthogonal regions and submachines. Overall, i am very happy with this
> library.

Cool :)

> But i am looking for a nice way to check if a state machine (e.g.
> instance mAvail of class AvailFSM) is in a given state, for example i
> would like to write something like this:
>
> assert(isInState(mAvail, AvailFSM::UpstreamAvailable()));
>
> I didn't find something like "isInState" provided by the MSM library, so
> i came up with the following implementation:
>
> template <class FSM, class StateType>
> bool isInState(const FSM& p, const StateType& s)
> {
> int stateId = boost::msm::back::get_state_id<typename
> FSM::stt,StateType>::value;
>
> for (int i=0; i < FSM::nr_regions::value; ++i)
> {
> if(p.current_state()[i] == stateId)
> {
> return true;
> }
> }
> return false;
> }
>
> This works well for simple state machines and orthogonal regions, but
> not for submachines. Does any one knows a way to extend the above code
> to work with submachines?

Hmmm not a bad idea indeed, I need to think about it, but in the
meantime I have another (and I think faster) solution. See below.

<snip>
> Currently i am using the following workaround:
>
> assert(isInState(mAvail, AvailFSM::UpstreamAvailable()));
> assert(isInState(mAvail.get_state<AvailFSM::UpstreamAvailable&>(),
> AvailFSM::UpstreamAvailable::Primary()));
>
> I consider this solution ugly not only because of its lengthiness, but
> also because "get_state" isn't a const function. Unfortunately i'am not
> deep enough into the template magic to tell if a const implementation of
> "get_state" is possible. Can anyone help me out ?

Usually, if you want to ask "isInState", you actually mean "is my fsm
in such a state that a property is true?". Next, what you will want
is:
 assert(isInState(mAvail, AvailFSM::UpstreamAvailable()) ||
isInState(...) && !... );

And this can pretty fast get much uglier as you need more and more conditions.
To that aim, MSM offers the concept of flags, allowing you to flag a
state with a certain property. You can then check if the property is
true with, say:
if (mAvail.is_flag_active<UpstreamOk>()) ...

Please have a look at (for 1.46 but any released version of MSM can do this):
http://www.boost.org/doc/libs/1_46_0/libs/msm/doc/HTML/ch03s02.html#d0e1110

Ah and it also works on submachines.

> So, to sum up, i have two questions:
> 1) How to implement something like "isInState" that even works on
> submachines, if possible ?

Would the offered solution satisfy your need?

> 2) Is a const version of "get_state" possible ? And how?

Sure. My mistake. Will be fixed in 1.47. Would you mind opening a
ticket so I don't forget it?

> best regards,
> jan

Best regards,
Christophe


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