[Boost-users] [statechart] history not saved

80 views
Skip to first unread message

Ilya Orlov

unread,
Nov 6, 2012, 10:34:23 AM11/6/12
to boost...@lists.boost.org
I have following code:

// from A11 and A12 and back
struct Ev1 : sc::event < Ev1 >{};
struct Ev2 : sc::event < Ev2 >{};

// from A to B and back
struct Ev3 : sc::event < Ev3 >{};
struct Ev4 : sc::event < Ev4 >{};

// from A1 to A2 and back
struct Ev5 : sc::event < Ev5 >{};
struct Ev6 : sc::event < Ev6 >{};

struct StateA;
struct StateA1;
struct StateA11;
struct StateA12;
struct StateA2;
struct StateA21;
struct StateA22;

struct StateB;

struct Machine : sc::state_machine < Machine, StateA > {};

struct StateA : sc::simple_state < StateA, Machine, mpl::list < sc::deep_history < StateA1 > >, sc::has_deep_history >
{
typedef sc::transition < Ev3, StateB > reactions;
};

struct StateA1 : sc::simple_state < StateA1, StateA, mpl::list < sc::deep_history < StateA11 > >, sc::has_deep_history >
{
typedef sc::transition < Ev5, StateA2 > reactions;
};

struct StateA11 : sc::simple_state < StateA11, StateA1 >
{
typedef sc::transition < Ev1, StateA12 > reactions;
};

struct StateA12 : sc::simple_state < StateA12, StateA1 >
{
typedef sc::transition < Ev2, StateA11 > reactions;
};

struct StateA2 : sc::simple_state < StateA2, StateA, mpl::list < sc::deep_history < StateA21 > >, sc::has_deep_history >
{
typedef sc::transition < Ev6, StateA1 > reactions;
};

struct StateA21 : sc::simple_state < StateA21, StateA2 > {};

struct StateA22 : sc::simple_state < StateA22, StateA2 > {};

struct StateB : sc::simple_state < StateB, Machine >
{
typedef sc::custom_reaction < Ev4 > reactions;

sc::result react(const Ev4&) { std::cout << "react" << std::endl; return transit < sc::deep_history < StateA11 > >(); }
};

I am sending events like this:

Machine m;
m.initiate();

std::cout << "Ev5" << std::endl;
m.process_event(Ev5());

std::cout << "Ev3" << std::endl;
m.process_event(Ev3());

std::cout << "Ev4" << std::endl;
m.process_event(Ev4());


After Ev5 machine goes to A2 -> A21 state.
After Ev3 machine leaves state A with history and goes to state B.
After Ev4 machine leaves state B and should go back to A2 -> A21 but actually goes to A -> A1 -> A11 - default states. 
How I can fix it?

Thanks,
Ilya

Andreas Huber

unread,
Nov 7, 2012, 3:19:51 PM11/7/12
to boost...@lists.boost.org
Hi Ilya

> After Ev5 machine goes to A2 -> A21 state.

> After Ev3 machine leaves state A with history and goes to state B.

> After Ev4 machine leaves state B and should go back to A2 -> A21 but actually
goes to A -> A1 -> A11 - default states. 

> How I can fix it?

From a cursory glance at the code, it seems it behaves as it should. Why do you
think that transitioning to deep history with default A11 should go to A2? It
seems you'd get what you want by transitioning to deep history with default A1.

HTH,

Andreas Huber

_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Ilya Orlov

unread,
Nov 7, 2012, 3:28:17 PM11/7/12
to boost...@lists.boost.org
Hi Andreas,

In there are no explanation of history types in documentation , just names - shallow, deep and full. I thought that with full history sm should go back to that state it was before leaving A state. 
Is it possible to go back to A2->A21 where it was before B in this case? And if yes, tell me please how to do it.

Thanks,
Ilya

Ilya Orlov

unread,
Nov 8, 2012, 5:51:36 AM11/8/12
to boost...@lists.boost.org
Sorry, Andreas,

I missed your advice in previous message. I changed transition code to A1 state and it worked perfectly. But ideally, I'd like to transit from B not to A1 but to A state. How I can change this code to get it working with saving all history for A-substates?

Thanks,
Ilya

On Thu, Nov 8, 2012 at 12:19 AM, Andreas Huber <ahd6974-spam...@yahoo.com> wrote:

Andreas Huber

unread,
Nov 8, 2012, 5:10:20 PM11/8/12
to boost...@lists.boost.org
Ilya Orlov <iorlov <at> gmail.com> writes:



> I missed your advice in previous message. I changed transition code to A1
state and it worked perfectly. But ideally, I'd like to transit from B not to
A1 but to A state. How I can change this code to get it working with saving all
history for A-substates?



I guess you are missing the fact that the template argument passed to
deep_history is actually the *default* *state*. This is the state that is
entered when no history has ever been saved. If history has been saved (as is
the case in your example code) then transit< sc::deep_history < StateA1 > >()
will transit to whatever inner state of A was active before A was exited. This
is explained in more detail here:



<http://www.boost.org/doc/libs/1_52_0/libs/statechart/doc/tutorial.html#History>



HTH,



Andreas Huber





P.S. In your example you're also specifying sc::deep_history< StateA1 > as
InnerInitial of A. So you could even transit directly to A, as follows:



return transit < StateA >();



and get exactly the same behavior as when you write:



return transit< sc::deep_history < StateA1 > >();

Ilya Orlov

unread,
Nov 9, 2012, 4:25:42 AM11/9/12
to boost...@lists.boost.org
On Fri, Nov 9, 2012 at 2:10 AM, Andreas Huber <ahd6974-spam...@yahoo.com> wrote:
Ilya Orlov <iorlov <at> gmail.com> writes:



> I missed your advice in previous message. I changed transition code to A1
state and it worked perfectly. But ideally, I'd like to transit from B not to
A1 but to A state. How I can change this code to get it working with saving all
history for A-substates?



I guess you are missing the fact that the template argument passed to
deep_history is actually the *default* *state*. This is the state that is
entered when no history has ever been saved. If history has been saved (as is
the case in your example code) then transit< sc::deep_history < StateA1 > >()
will transit to whatever inner state of A was active before A was exited. This
is explained in more detail here:



<http://www.boost.org/doc/libs/1_52_0/libs/statechart/doc/tutorial.html#History>

In fact I did not missed this part of tutorial. But since documentation is almost non-existent in area of history types description, my first attempt was to set the same default state (A11) in every declaration of A substates. My idea here was that if I stated deep_history for A substates and for A itself, all history will be saved and we need default state only if there was not action inside A state before transition into it. So A should have only one default state. For me it makes sense. But it did not worked for me at all. 
Next, I defined different default states for each direct A substate. I still dont understand why I should do it and how it could be that A have several default substates. At the same time I added transition from B to one of exact default states. For A1 default state was A11 and I put it into return transit < sc::deep_history < StateA11 > >(); My thought here was if I defined A11 as default state, all transactions to A should use exactly this state. This did not worked too, as I described in my first message.
And next, using your advice I changed transit from A11 to A1, but I still dont understand why I should do it this way.
As for me, most logical behavior should be like this - if A uses deep history (I take it as 'total history for all substates'), A should have single default state for cases like this C -> B -> A. But for cases A -> B -> A in B -> A transition user should use outermost state A in transition destination and do not care about how history is saved inside it or about its default state. 

Thanks,
Ilya

Andreas Huber

unread,
Nov 11, 2012, 7:39:21 AM11/11/12
to boost...@lists.boost.org
> In fact I did not missed this part of tutorial. But since documentation is

> almost non-existent in area of history types description,



Boost.Statechart implements the state machine semantics defined by the UML
standard, which is mentioned in the documentation. I hope you understand that
describing how FSM history works is therefore beyond the scope of the
documentation.



> As for me, most logical behavior should be like this - if A uses deep

> history (I take it as 'total history for all substates'), A should have

> single default state for cases like this C -> B -> A.



IIUC, what you find most logical is contrary to what UML defines. Moreover, in
practice it does happen that you need different default states for different
transitions to history.



> But for cases

> A -> B -> A in B -> A transition user should use outermost state A in

> transition destination and do not care about how history is saved inside

> it or about its default state.



As I've mentioned before, you *can* have exactly what you describe here. In
your code, please replace the line



return transit< sc::deep_history < StateA1 > >();



with



return transit < StateA >();



and you should see exactly the same behavior.



This works because StateA specifies sc::deep_history < StateA1 > as its inner
initial state.



Regards,



Andreas
Reply all
Reply to author
Forward
0 new messages