Thanks for your feedback and yea, Boost.MSM is great; eUML is even better,
but it was written some time ago, before C++11.
It still uses Boost.MPL and Boost.Fusion which are pretty slow to compile
in comparison to
what can be achieved nowadays. On top of that, right now we have a lambda
expressions which were
emulated in eUML using Boost.Phoenix. All in all, C++11/14 give as a lot of
opportunities
to improve the situation and Boost.MSM-lite is just a small example how
much more user-friendly C++ might be
as well as how much faster the code might be compiled without loosing any
performance.
On Thu, Jan 28, 2016 at 5:44 PM, Klaim - Joël Lamotte <mjk...@gmail.com>
wrote:
> Le 01/02/2016 11:57, Kris a écrit :
>
>> Hi Christophe,
>>
>> Thank you very much for your feedback and time. I appreciate it a lot.
>>
>> Yea, I like having everything visible on the transition table and
>> therefore
>> I put initial states as well entry/exit actions there.
>> I know you have a different view on that, however, I find it easier to
>> follow this way.
>>
>> Declare events on the fly its easy to do, however, I don't think it will
>> bring much value as events can be accessed outside
>> the transition table as well as they, most likely, will hold some data.
>> Therefore, I'm not sure about it. Might be useful to have
>> both options tho.
>>
>> I would love to compare MSM-lite/MSM-eUML to eUML2, however I haven't seen
>> it yet besides some code in the emails.
>> Can you share a link to the eUML2 version, please? I will defo add
>> benchmarks for it.
>>
>> I don't see any problem with that as MSM-lite is open source. I also offer
>> my help in designing and/or coding.
>>
> Hi, IIUC you are proposing a 3rd MSM library in Boost, and you don't
> pretend to make it a sub-library of Boost.MSM. If I'm right, I suggest you
> to rename the namespace to msm_lite or whatever you find more appropriated.
>
Fair point, thanks for pointing it out. It's a valid concern. I have
nothing against changing the namespace/name as 'msm-lite' is just a working
title either way. Not sure what the best name should be tho?
> BTW, with the figures you gave I believe that there would be an interest
> in your library.
>
>>
>> Well, I would like to keep the core of the library as small as possible as
>> in my experience a lot of users are actually not using
>> as many features. Having said that, I have no problems adding new features
>> via policies/extensions. Moreover, MSM-lite
>> is already used in some of the top growing mobile games, but yea, I do
>> agree that some users would like to see more features.
>> Anyway, are there any specific features you are talking about which are so
>> essential. I know that defer/history might be useful,
>> but I don't see much more features in MSM, besides explicit/fork states?
>>
> Well these are already quite a few features. I have not see local
> transitions (different from internal transitions).
Yea interna(local) transitions are supported. Example here ->
http://boost-experimental.github.io/msm-lite/examples/index.html#transitions
>
>
Please could you point me if you support choice points?
While choice points are unavoidable in graphical UML, I find it not very
> useful while writing MSM in C++ as I prefer to do it using if or switch.
> However having a transition table that can have only one next-state by
> transition disable this possibility. I use to have a transition table with
> a transition that has an action_nextstate that do the action and returns
> the nextstate of the transition.
>
> |"s2"_s + event<e2> [ guard ] / action_nextstate This avoids the storage
> of local variable on the MSM data context. |
>
>
> Have you considered this possibility?
>
Interesting idea, can you elaborate please as I'm not sure whether I follow
the idea with the action_nextstate?
If it comes to the choice points, I guess the easier way is just to have
multiple transitions from the same state?
make_transition_table(
s1 -> s2 + e2 [some_guard1 && some_guard2] / action1
, s1 -> s3 + e2 [other_guard] / action2
, s1 + e2 / action3
);
would be the same as
if (e2) {
if (some_guard1 && some_guard2) {
action1;
change_state_to(s2);
} else if(other_guard) {
action2;
change_state_to(s3);
} else {
action3;
}
}
>
> Best,
> Vicente
>
Thank you for you feedback.
Cheers, Kris
> On 2 February 2016 at 19:41, Vicente J. Botet Escriba <
> vicent...@wanadoo.fr> wrote:
>
> >
> > I see that MSM eUML defines the transitions like
> >
> > target == source + event [guard] / action
> >
> > but MSM-lite reverse the source and target
> >
> > src_state == dst_state + event[ guard ] / action This is confusing.
> >
> > Why have you chosen this syntax? Vicente
> >
> >
>
> Same question here. I misread the examples at first because the meaning is
> reversed.
> It feels unnatural that the state you are going to is part of the
> expression stating the conditions to get there.
>
> The MSM syntax is clearer to me at least.
I see your point. It seems like I will have to change the default behaviour
then as it's clearer for most devs. Guess, I'm the ackward one here.
Please, check the euML emulation example ->
http://boost-experimental.github.io/msm-lite/examples/index.html#euml-emulation
as DSL
behaviour might be changed if it comes to states order by defining
BOOST_MSM_DSL_DST_STATE_FIRST.
If it comes to the transition table DSL. I was concidering a lot of
options. For example MSM3(eUML2) is using src + event [guard] / action ->
dst
which looks great, however, having a dst state at the end is not really
practical, especially after a lot of noice introduced by guard and actions
(for example in place lambda expressions).
Right now, I'm thinking of introducing DSL which would look like that.
make_transition_table(
"idle* -> state1"_t + event [ guard ] / action
, "state1 -> X"_t [ guard ] / action
);
Nevertheless, I'm not sure whether such approach would be seen positively
because following MSM approach it should be more like that.
make_transition_table(
"state1 <- idle*"_t + event [ guard ] / action
, "X <- state1"_t [ guard ] / action
);
which looks confusing for me. Any thought on this?
Thanks for your feedback,
Cheers, Kris
I was going to suggest <= and => but I don't know the potential problems.
> On 2 February 2016 at 22:29, Krzysztof Jusiak <[hidden email]
> <http:///user/SendEmail.jtp?type=node&node=4683151&i=0>> wrote:
>
> > On Tue, Feb 2, 2016 at 7:09 PM, Klaim - Joël Lamotte <[hidden email]
> <http:///user/SendEmail.jtp?type=node&node=4683151&i=1>>
> > wrote:
> >
> > > On 2 February 2016 at 19:41, Vicente J. Botet Escriba <
> > > [hidden email] <http:///user/SendEmail.jtp?type=node&node=4683151&i=2>>
It's a compile time string parsing so there are no issues with characters
here, just the design.
So your suggestion would be:
// *=initial
"state1 <= idle*"
or
"idle* => state1"
is that correct?
'->' was chosen, simply because it might be found in the UML2
specification, but there are no limitations here. Whatever works the best.
Thanks for the suggestion, Kris
>
> > Thanks for your feedback,
> > Cheers, Kris
> >
> >
> > _______________________________________________
> > > Unsubscribe & other changes:
> > > http://lists.boost.org/mailman/listinfo.cgi/boost
> > >
> >
> > _______________________________________________
> > Unsubscribe & other changes:
> > http://lists.boost.org/mailman/listinfo.cgi/boost
> >
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>
> ------------------------------
> If you reply to this email, your message will be added to the discussion
> below:
>
> To unsubscribe from [MSM] Is there any interest in C++14 Boost.MSM-eUML
> like library which compiles up to 60x quicker whilst being a slightly
> faster too?, click here
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4683016&code=a3J6eXN6dG9mQGp1c2lhay5uZXR8NDY4MzAxNnwtMTY0MTkzNTIwMA==>
> .
> NAML
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>
--
View this message in context: http://boost.2283326.n4.nabble.com/MSM-Is-there-any-interest-in-C-14-Boost-MSM-eUML-like-library-which-compiles-up-to-60x-quicker-whils-tp4683016p4683152.html
Sent from the Boost - Dev mailing list archive at Nabble.com.
_______________________________________________
make_transition_table(
s0 + e / action0 -> cp
cp [some_guard1] / action1 -> s1
cp [else] / action2 -> s2
);
With action-next-state transition could be
s0 + e / action_nextstate
where action_nextstate is
auto action_nextstate = [](auto const& evt) {
action0;
if (some_guard1) {
action1;
next_state(s1); // You could also return a state if there is a
type that can store any state of the state machine.
} else {
action2;
next_state(s2);
}
}
Note that these action-nextstate could define some local variables in
action0 that can be used in some_guard1 and in action1 and action2 .
The uml transition schema forces to store these local variable on the
state machine context (or a state context if supported), which is less
than optimal. This is needed because there is no way to share variables
between the action0, some_guard1 and in action1 and action2. In addition
action1 and action2 have no access to the event e, as only the action0
has it as parameter.
Do you think that this kind of transitions goes against the UML semantics?
Best,
Vicente
> Le 02/02/2016 22:12, Krzysztof Jusiak a écrit :
>
> > On Tue, Feb 2, 2016 at 6:19 PM, Vicente J. Botet Escriba <
> > [hidden email] <http:///user/SendEmail.jtp?type=node&node=4683171&i=0>>
> wrote:
> >
> >> Le 01/02/2016 11:57, Kris a écrit :
> >>
> >>>
> >> Hi, IIUC you are proposing a 3rd MSM library in Boost, and you don't
> >> pretend to make it a sub-library of Boost.MSM. If I'm right, I suggest
> you
> >> to rename the namespace to msm_lite or whatever you find more
> appropriated.
> >>
> > Fair point, thanks for pointing it out. It's a valid concern. I have
> > nothing against changing the namespace/name as 'msm-lite' is just a
> working
> > title either way. Not sure what the best name should be tho?
> Well, you would need to choose a name ;-)
> >
> >
> >>
> >> Well these are already quite a few features. I have not see local
> >> transitions (different from internal transitions).
> >
> > Yea interna(local) transitions are supported. Example here ->
> >
> http://boost-experimental.github.io/msm-lite/examples/index.html#transitions
> >
> Internal and local transitions are not the same. How do you make
> syntactically the difference. I've not see and reference to local
> transitions.
>
> Actually, I'm not sure what the difference is, sorry. I checked the UML2
spec and there is no much
about local transitions there. Bascially that, 'internal is a special case
of a local Transition that is a self-transition'.
Can you explain how it supose to work, please and what syntax would be
preferable?
Actually msm-lite, since today, supports almost this syntax. There are
pre/post fix notations available.
src_state + event [guard] / action = dst_state
or
dst_state <= src_state + event [guard] / action
Hmm, interesting idea. However, it seems to be against the transition table
concept a bit
as guards are hidden in the actions instead. I do understand the concept
tho, it's more
like custom_reaction in the Boost.Statechart. I would still model it using
transition table
because it makes it more visible/clear to understand what is going on. With
action_nexstate approach
you have to check all actions to verify whether they are not changing the
state which might
be tricky to do. Unless, you have a solution for that?
BTW. msm-lite has a bit different approach than MSM to share the data
because guards/actions
may share data as objects are injected into them when they are required.
For example,
auto action = [] {}; // action, not data, no event
auto action_with_some_data = [] (int i, data& d) {}
auto action_with_some_data_and_event = [] (int i, const auto & event, data&
d) {} // order doesn't matter
auto guard_with_data = [] (data& d, const auto& event) { return true; }
make_transition_table(
*s1 + e1 [ guard_with_data ] / action = s2
, s2 + e2 / (action_with_some_data, action_with_some_data_and_event)
);
data d;
sm fsm{d, 42}; // order doesn't matter, this data will be injected into
guards/actions
It's a bit tedious to pass all required objects into state machine
constructor and therefore depenendy injection framework
may become handy here, for example experimental boost.di ->
https://github.com/boost-experimental/di
More examples:
http://boost-experimental.github.io/msm-lite/examples/index.html#actions-guards
http://boost-experimental.github.io/msm-lite/examples/index.html#dependency-injection
Thanks for your feedback, Kris
>
> Best,
> Vicente
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>
> ------------------------------
> If you reply to this email, your message will be added to the discussion
> below:
>
> To unsubscribe from [MSM] Is there any interest in C++14 Boost.MSM-eUML
> like library which compiles up to 60x quicker whilst being a slightly
> faster too?, click here
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4683016&code=a3J6eXN6dG9mQGp1c2lhay5uZXR8NDY4MzAxNnwtMTY0MTkzNTIwMA==>
> .
> NAML
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>
--
View this message in context: http://boost.2283326.n4.nabble.com/MSM-Is-there-any-interest-in-C-14-Boost-MSM-eUML-like-library-which-compiles-up-to-60x-quicker-whils-tp4683016p4683175.html
Sent from the Boost - Dev mailing list archive at Nabble.com.
_______________________________________________
An internal transition don't exits at all.
I have no preference for the notation, but why not replace the + sign
with a ^
src ^ event [guard] / action = src
src ^ event [guard] / action = src(H)
>>> Please could you point me if you support choice points?
>>>
> Actually msm-lite, since today, supports almost this syntax. There are
> pre/post fix notations available.
> src_state + event [guard] / action = dst_state
> or
> dst_state <= src_state + event [guard] / action
I know.
I'll take a look at. Yes, this can be seen as a drawback as less
visible, but performances are important in C++.
> I would still model it using
> transition table
> because it makes it more visible/clear to understand what is going on. With
> action_nexstate approach
> you have to check all actions to verify whether they are not changing the
> state which might
> be tricky to do. Unless, you have a solution for that?
One possibility is to return the next-state.
You could also restrict the possible next states in the table.
s0 + e / action_nextstate(s1, s2)
>
> BTW. msm-lite has a bit different approach than MSM to share the data
> because guards/actions
> may share data as objects are injected into them when they are required.
> For example,
>
> auto action = [] {}; // action, not data, no event
> auto action_with_some_data = [] (int i, data& d) {}
> auto action_with_some_data_and_event = [] (int i, const auto & event, data&
> d) {} // order doesn't matter
>
> auto guard_with_data = [] (data& d, const auto& event) { return true; }
>
> make_transition_table(
> *s1 + e1 [ guard_with_data ] / action = s2
> , s2 + e2 / (action_with_some_data, action_with_some_data_and_event)
> );
>
> data d;
> sm fsm{d, 42}; // order doesn't matter, this data will be injected into
> guards/actions
Hmm, this will not reduce the size of the shared data. What I want is to
be able to use local data shared between transition segments. This local
could be encoded in the transition table, but I'm not sure it is worth
the effort.
> It's a bit tedious to pass all required objects into state machine
> constructor and therefore depenendy injection framework
> may become handy here, for example experimental boost.di ->
> https://github.com/boost-experimental/di
>
> More examples:
> http://boost-experimental.github.io/msm-lite/examples/index.html#actions-guards
> http://boost-experimental.github.io/msm-lite/examples/index.html#dependency-injection
>
>
I don't understand how this helps in this context.
> Le 03/02/2016 21:48, Kris a écrit :
>
> > On Wed, Feb 3, 2016 at 6:48 PM, Vicente Botet [via Boost] <
> > [hidden email] <http:///user/SendEmail.jtp?type=node&node=4683180&i=0>>
I have seen it, thanks. Yea, local transitions are not supported currently
by msm-lite.
Are they supported by MSM? I haven't seen support for it there too. Anyway,
they are
not hard to implement. Do you have any important use case for them?
>
> An internal transition don't exits at all.
>
> I have no preference for the notation, but why not replace the + sign
> with a ^
>
> src ^ event [guard] / action = src
>
> src ^ event [guard] / action = src(H)
>
>
Well, I have just followed MSM approach and '+' was used there and I was
fine with it.
Is there any reason why '+' is wrong and it should be replaced with '^'
instead?
I implemented action_nextstate, so please take a look.
It might be checked online HERE ->
http://melpon.org/wandbox/permlink/IMZUWJpiHDP62WEO
It's really easy to implement it, the basic idea below.
auto action_nextstate = [](auto... s) {
std::tuple<decltype(s)...> states{s...};
return [=](msm::sm<auto>& sm, auto const& evt, bool external_value) {
action0();
if (some_guard1(external_value)) {
action1();
sm.change_state(std::get<0>(states));
} else {
action2(evt);
sm.change_state(std::get<1>(states));
}
};
};
I had to add `change_state` to the msm-lite as it doesn't support changing
states unless in testing mode.
template <class... TStates>
void change_state(const detail::state<TStates> &...) noexcept {
decltype(current_state_) new_states = {aux::get_id<states_ids_t, 0,
TStates>()...};
*current_state_ = *new_states;
}
I hope that helps.I do understand your concept, however I'm not sure
whether such approach
is the best, but, at least, it's easy to implement. I guess if you can
prove that this is a common
case and that performance might be gained using it then it's worth to
consider such practice in general.
>
> > BTW. msm-lite has a bit different approach than MSM to share the data
> > because guards/actions
> > may share data as objects are injected into them when they are required.
> > For example,
> >
> > auto action = [] {}; // action, not data, no event
> > auto action_with_some_data = [] (int i, data& d) {}
> > auto action_with_some_data_and_event = [] (int i, const auto & event,
> data&
> > d) {} // order doesn't matter
> >
> > auto guard_with_data = [] (data& d, const auto& event) { return true; }
> >
> > make_transition_table(
> > *s1 + e1 [ guard_with_data ] / action = s2
> > , s2 + e2 / (action_with_some_data, action_with_some_data_and_event)
> > );
> >
> > data d;
> > sm fsm{d, 42}; // order doesn't matter, this data will be injected into
> > guards/actions
> Hmm, this will not reduce the size of the shared data. What I want is to
> be able to use local data shared between transition segments. This local
> could be encoded in the transition table, but I'm not sure it is worth
> the effort.
Me neither, so again, please take a look into the example and experiment
with it (http://melpon.org/wandbox/permlink/IMZUWJpiHDP62WEO). It's
defo worth trying it out.
> > It's a bit tedious to pass all required objects into state machine
> > constructor and therefore depenendy injection framework
> > may become handy here, for example experimental boost.di ->
> > https://github.com/boost-experimental/di
> >
> > More examples:
> >
> http://boost-experimental.github.io/msm-lite/examples/index.html#actions-guards
> >
> http://boost-experimental.github.io/msm-lite/examples/index.html#dependency-injection
> >
> >
> I don't understand how this helps in this context.
>
Probably is not as your idea is based on local and not external data. I
misunderstood your concept at first.
>
> Vicente
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>
> ------------------------------
> If you reply to this email, your message will be added to the discussion
> below:
>
> To unsubscribe from [MSM] Is there any interest in C++14 Boost.MSM-eUML
> like library which compiles up to 60x quicker whilst being a slightly
> faster too?, click here
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4683016&code=a3J6eXN6dG9mQGp1c2lhay5uZXR8NDY4MzAxNnwtMTY0MTkzNTIwMA==>
> .
> NAML
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>
--
View this message in context: http://boost.2283326.n4.nabble.com/MSM-Is-there-any-interest-in-C-14-Boost-MSM-eUML-like-library-which-compiles-up-to-60x-quicker-whils-tp4683016p4683203.html
Sent from the Boost - Dev mailing list archive at Nabble.com.
_______________________________________________
> Le 03/02/2016 22:32, Kris a écrit :
>
> > On Wed, Feb 3, 2016 at 8:54 PM, Christophe Henry-2 [via Boost] <
> > [hidden email] <http:///user/SendEmail.jtp?type=node&node=4683181&i=0>>
> wrote:
> >
> >>> Moreover, I'm not sure how to disable the slowing down options such as
> >> deffered events etc.?
> >>
> >> I would be surprised if deferred events costed much compile time.
> >>
> >> Yea, I agree that compilation time should not be affected. However a
> > runtime performance could have, right?
> Event deferral must not cost anything at run-time if not used. Otherwise
> it should be provided at a higher level.
>
> The same applies to history state.
>
> Of course, these features imply some extra space.
>
>
Totally agree and this approach is taken by msm-lite as well as MSM.
However, you can see that eUML2 (successor of eUML) is slower than eUML in
the sample test
and therefore my confusion if it didn't have those features turned on by
default as the same
back-end is used for both.
http://boost-experimental.github.io/msm-lite/overview/index.html#performance
MSM requires to turn defferal events/queue etc. by adding a typedef
to the state machine. All in all, it is just an assumption as I don't know
the implementation details of eUML2, maybe it's just slower?
> Vicente
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>
>
> ------------------------------
> If you reply to this email, your message will be added to the discussion
> below:
>
> To unsubscribe from [MSM] Is there any interest in C++14 Boost.MSM-eUML
> like library which compiles up to 60x quicker whilst being a slightly
> faster too?, click here
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4683016&code=a3J6eXN6dG9mQGp1c2lhay5uZXR8NDY4MzAxNnwtMTY0MTkzNTIwMA==>
> .
> NAML
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>
--
View this message in context: http://boost.2283326.n4.nabble.com/MSM-Is-there-any-interest-in-C-14-Boost-MSM-eUML-like-library-which-compiles-up-to-60x-quicker-whils-tp4683016p4683205.html
Sent from the Boost - Dev mailing list archive at Nabble.com.
_______________________________________________
std::get<0>(states) doesn't scale.
Passing all the states each time to the action_nextstate will not be the more efficient way.
The states tuple are part of the lambda so the SM will store the tuple of states once for each transition. Even if this is not instantiated for each instance of the SM, this seems unnecessary.
I would suggest to have a single SM context that stores anything needed and let each transition have access to it.
> I do understand your concept, however I'm not sure
> whether such approach
> is the best, but, at least, it's easy to implement. I guess if you can
> prove that this is a common
> case and that performance might be gained using it then it's worth to
> consider such practice in general.
How many times you receive a message and depending on the message
contents and the SM data context your SM will go to one state or another?
I don't know how I could prove that this is quite common, but I can
ensure you that it is ;-)
For performances, there is already the space performances, there is no
need to store local variable on the state machine context, and this can
grow quickly.
For runtime, you avoid calling to process event on each transition
segment, the code of a transition been in a single function the compiler
can inline, optimize, ...
Note that I'm not saying that MSM-lite should not support eUML2 transitions.
>> I do get your point now. It's a valid feature. I added a task to
investigate/implement local transitions. However, I can't promise when the
implementation will be done. Firstly, I have to finish the support for
defering events.
>
>> An internal transition don't exits at all.
>>>
>>> I have no preference for the notation, but why not replace the + sign
>>> with a ^
>>>
>>> src ^ event [guard] / action = src
>>>
>>> src ^ event [guard] / action = src(H)
>>>
>>>
>>> Well, I have just followed MSM approach and '+' was used there and I was
>> fine with it.
>> Is there any reason why '+' is wrong and it should be replaced with '^'
>> instead?
>>
> You misunderstood me. + will represent external transitions, while ^
> could represent local transitions.
>
Yea, I do get it know. Thanks for explanations.
Fair do's, it ain't perfect. However, it doesn't have to be done this way.
I mean, states don't even have to be passed into action_nextState at all,
which makes the implemention clener and easier to follow.
So, the new version would look like that.
auto action_nextstate = [](msm::sm<auto>& sm, auto const& evt, bool
external_value) {
action0();
if (some_guard1(external_value)) {
action1();
fsm(sm).set_current_states("s1"_s);
} else {
action2(evt);
fsm(sm).set_current_states("s2"_s);
}
};
and transition table
return make_transition_table(
*"idle"_s + "event"_t / action_nextstate
, "s1"_s + "event"_t / [] { std::cout << "in s1" << std::endl; }
, "s2"_s + "event"_t / [] { std::cout << "in s2" << std::endl; }
);
BTW. This version is achieved without any changes to the current version of
msm-lite because setting states is done via testing extension.
Working example here -> http://melpon.org/wandbox/permlink/2SJCL6WAK0n9q7bs
>
> I would suggest to have a single SM context that stores anything needed
> and let each transition have access to it.
I don't like 'God objects'. IMHO, it's way better to inject whatever is
required by guards/actions. It's easier to test and maintain it this way
and there is no need for a SM context in the action_nextState example.
> I do understand your concept, however I'm not sure
>> whether such approach
>> is the best, but, at least, it's easy to implement. I guess if you can
>> prove that this is a common
>> case and that performance might be gained using it then it's worth to
>> consider such practice in general.
>>
> How many times you receive a message and depending on the message contents
> and the SM data context your SM will go to one state or another?
> I don't know how I could prove that this is quite common, but I can ensure
> you that it is ;-)
>
> For performances, there is already the space performances, there is no
> need to store local variable on the state machine context, and this can
> grow quickly.
>
> For runtime, you avoid calling to process event on each transition
> segment, the code of a transition been in a single function the compiler
> can inline, optimize, ...
>
> Note that I'm not saying that MSM-lite should not support eUML2
> transitions.
Okay, I see your points. I guess usage of action_nextState might be
justified and might be easily implemented in msm-lite too.
> Le 28/01/2016 17:19, Krzysztof Jusiak a écrit :
>
>> Dear Boosters,
>>
>> I have recently released 1.0.0 version of experimental C++14
>> Boost.MSM-lite.
>> Your scalable C++14 header only eUML-like meta state machine library with
>> no dependencies, which outperform Boost.MSM - eUML in:
>> - faster compilation times - up to 60x times faster!
>> - smaller executable size - up to 15x smaller
>> - slightly better performance
>> - smaller memory usage
>> - short error messages
>>
>>
>> Hi,
>
> I have not found anything about how exceptions are managed nor about
> inheritance of state machines. Is there something related to these two
> subjects on your library?
>
>
It's a valid point. Documentation was lacking much info about exceptions
safety. I've just added it here ->
http://boost-experimental.github.io/msm-lite/overview/index.html#exception-safety
Currently, there is no much policy about exception handling though.
However, if guard/action throws state machine will be in a defined state.
Any problems you have encountered with the exceptions? Suggestions are more
than welcome as I'm not sure what would be the best solution here.
Can you elaborate what you mean by `inheritance of state machines`, please?
Is the question related to composite/sub state machines or just whether a
state machine might be inherited?
Best,
> Vicente
>
> P.S. Sorry, I don't know how MSM or statecharts covers these subjects.
>
>
MSM has a policy called `no_exception` which basically disable catching
exceptions. Otherwise they are caught within the process_event.
Don't know how statechart is handling it.
Thanks for the pointer.
With the UML2 transition model is harder to manage with exceptions, as
the next state is on the transition table and the the engine must be
concerned.
I don't understand clearly the different behavior when exceptions
escapes a guard or an action. Changing to the next state could call to
the entry of the state. In any case what you proposes don't allow to
handle the exception at a higher level.
My preference is to go to an associated catch exception 'pseudo state'
and request the process of an associated exception event.
I believe that we could add an associated catch pseudo-state
src_st + event [guard] / action = dst_st|catch_st
When there is an exception on this transition the catch_st is entered
and an exception event is handled.
catch pseudo states can also be associated to an state so that it acts
as the default catch state for all the transitions from this state. We
can see also an upper state as a exception-catcher.
src_st + event [guard] / action = dst_st
If an exception is throw on guard or action, the exception event is
handled on the nesting state of src_st.
The interest of having local transition segments is that the exit of the
current state is not called until there is an external transition segment.
src_st ^ event [guard] / action = dst_st
If an exception is throw on guard or action, the exception event is
handled on src_st.
An exception throw on the dst_st entry should be handled by its nesting
state.
Associating a single TOP level state to a SM allows to associate a catch
state to the SM.
Of course transitions that throw from the catch state associated to the
top level should be transported to the caller or the sender (depending
on whether the mechanism is synchronous or asynchronous).
You can find some descriptions of UML and exception handling e.g. at [1]
for activities or [2]. Look for UML exception handling on your preferred
search engine.
Note that when we use the action_nextstate model, the action_next can
catch the exception and do whatever is needed and possible go to a
specific state after handling the error.
I don't know if all this is compatible with UML2 model, I believe UML2
doesn't model exceptions (C++ exceptions) on guards/actions. There is
the concept of an exception signal, but I'm not sure this respond to
what I'm asking for.
> Suggestions are more
> than welcome as I'm not sure what would be the best solution here.
>
> Can you elaborate what you mean by `inheritance of state machines`, please?
> Is the question related to composite/sub state machines or just whether a
> state machine might be inherited?
A derived state machine can refine a base state machine in different ways:
1* adding new transitions
2* refining a state by adding sub-states and transitions
3* refining the next state of a transition with a sub-state of the
derived next state (or an entry point, but I believe that MSM-lite has
no entry/exit points associated to an state, isn't it?)
4* refining the guard of a transition
5* refining the action of a transition
I'm for at least the 3 first extension mechanisms. The last two can be
emulated with virtual functions.
Point 3* could be not needed if the base class transitions make use of
entry points.
[3] presents an OOHSM with abstract states.
>
> P.S. Sorry, I don't know how MSM or statecharts covers these subjects.
>
>
> MSM has a policy called `no_exception` which basically disable catching
> exceptions. Otherwise they are caught within the process_event.
Do you know what MSM does with the caught exception?
> Don't know how statechart is handling it.
>
>
Vicente
[1] http://edn.embarcadero.com/article/30169
[2]
https://www.google.fr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&cad=rja&uact=8&ved=0ahUKEwipzI_H2OHKAhWG2hoKHRHZCuwQFgg3MAI&url=http%3A%2F%2Fwww.mit.bme.hu%2F~pinter%2Fpublications-files%2Fpinter-majzik-2004-fidji-modeling-and-analysis-of-exception-handling-techniques-by-using-uml-statecharts.pdf&usg=AFQjCNEkHdkPZJT2Cn7A8qAyHXJ4W5zcrw&sig2=q5oZ9NfLd7GXnWkFdprb7Q
[3]
https://www.google.fr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=7&cad=rja&uact=8&ved=0ahUKEwjxp8qm3-HKAhWGWhQKHdnRA60QFghRMAY&url=http%3A%2F%2Fwww2.ic.uff.br%2F~esteban%2Ffiles%2Fcadabra.pdf&usg=AFQjCNE5KJWQr4m0RB87cgrnKFLDKjBj1A&sig2=uC0-Zikp3OoZVNjzXMUTJw
Thanks for materials and ideas. It's a really intresesting idea with the
pseudo states. I'm not sure if it is not to complex for msm-lite, but I
will defo take a look.
Your approach also gave me and idea to add exception handling into the
transition table the way events are handled too. Not sure about such
approach, but I guess, it's worth to consider too.
src + event [guard]/action = dst // guard throws runtime_error
src + exception<runtime_error> = X // handle exception
Anyway, I have created a ticket for it here ->
http://boost-experimental.github.io/msm-lite/TODO/index.html
>
> Suggestions are more
>> than welcome as I'm not sure what would be the best solution here.
>>
>> Can you elaborate what you mean by `inheritance of state machines`,
>> please?
>> Is the question related to composite/sub state machines or just whether a
>> state machine might be inherited?
>>
> A derived state machine can refine a base state machine in different ways:
>
> 1* adding new transitions
> 2* refining a state by adding sub-states and transitions
> 3* refining the next state of a transition with a sub-state of the derived
> next state (or an entry point, but I believe that MSM-lite has no
> entry/exit points associated to an state, isn't it?)
>
Not yet, explicit entry/exit points are not supported yet.
> 4* refining the guard of a transition
> 5* refining the action of a transition
>
> I'm for at least the 3 first extension mechanisms. The last two can be
> emulated with virtual functions.
> Point 3* could be not needed if the base class transitions make use of
> entry points.
>
>
Okay, well, msm-lite doesn't support that as a feature. However, you can
achieve more or less all of mentioned things just by using C++.
For example, you can extend transiton table of a state machine by joining
it with another one.
auto table1 = make_transition_table(transitions...);
auto table2 = make_transition_table(table1, other_transitions...);
> [3] presents an OOHSM with abstract states.
>
>>
>> P.S. Sorry, I don't know how MSM or statecharts covers these subjects.
>>
>>
>> MSM has a policy called `no_exception` which basically disable catching
>> exceptions. Otherwise they are caught within the process_event.
>>
> Do you know what MSM does with the caught exception?
By default assert will be called, but you can override the default
behaviour by adding your custom handler to the state machine.
template <class FSM,class Event>
void exception_caught (Event const&,FSM&,std::exception& ) {
... // handle exception here
It would be great if you show how the user can address these points with
your library using some run-able concrete examples.
Vicente
> Le 06/02/2016 22:07, Krzysztof Jusiak a écrit :
>
> > On Sat, Feb 6, 2016 at 12:03 AM, Vicente J. Botet Escriba <
> > [hidden email] <http:///user/SendEmail.jtp?type=node&node=4683294&i=0>>
> wrote:
> >
> >> Le 05/02/2016 22:30, Krzysztof Jusiak a écrit :
> >>
> > Thanks for materials and ideas. It's a really intresesting idea with the
> > pseudo states. I'm not sure if it is not to complex for msm-lite, but I
> > will defo take a look.
> > Your approach also gave me and idea to add exception handling into the
> > transition table the way events are handled too. Not sure about such
> > approach, but I guess, it's worth to consider too.
> >
> > src + event [guard]/action = dst // guard throws runtime_error
> > src + exception<runtime_error> = X // handle exception
> Yes, this is the idea.
Great. I have improved error handling if it comes to exceptions.
Right now, if you do NOT compile with `-fno-exceptions` and do not specify
configure noexcept then you can handle any exceptions thrown on the
transition table.
make_transition_table(
*"idle"_s + "event1"_t / [] { throw std::runtime_error{"error"}; }
, "idle"_s + "event2"_t / [] { throw 0; }
, *"error_handling"_s + exception<std::runtime_error> / [] { std::cout <<
"exception caught" << std::endl; }
, "error_handling"_s + exception<> / [] { std::cout << "generic
exception caught, terminate..." << std::endl; } = X
);
You can handle specific type of the exception(exception<type>) or just
any(exception<>).
Improved documentation and examples here:
*
http://boost-experimental.github.io/msm-lite/overview/index.html#exception-safety
*
http://boost-experimental.github.io/msm-lite/tutorial/index.html#8-error-handling
*
http://boost-experimental.github.io/msm-lite/examples/index.html#error-handling
I was wondering whether your point with extending transitions can't be
achieved using sub machines instead ? For example.
struct example {
auto configure() const noexcept {
using namespace msm;
return make_transition_table(
*"idle"_s + event<e1> / [] { std::cout << "in sub sm" << std::endl;
} = "s1"_s
, "s1"_s + event<e2> / [] { std::cout << "finish sub sm" <<
std::endl; } = X
);
}
};
struct extend_example
auto configure() const noexcept {
using namespace msm;
state<sm<example>> composite;
return make_transition_table(
*composite = composite // composite region
//-----------------------------------//
// add new transitions for error handling
, *"error_handling"_s + unexpected_event<> / [] { std::cout <<
"unexpected event, terminate..." << std::endl; } = X
, "error_handling"_s + exception<std::runtime_error> / [] { std::cout
<< "exception caught" << std::endl; }
, "error_handling"_s + exception<> / [] { std::cout << "generic
exception caught, terminate..." << std::endl; } = X
);
}
};
Right now,
sm<example> sm;
sm.process_event(e1{}); // handled by example
sm.process_event(e2{}); // handled by example
sm.process_event(e3{}); // handled by extended_example error handling
>
> It would be great if you show how the user can address these points with
> your library using some run-able concrete examples.
>
Yea, I will work on that. Cheers for the pointers.
> Vicente
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>
> ------------------------------
> If you reply to this email, your message will be added to the discussion
> below:
>
> To unsubscribe from [MSM] Is there any interest in C++14 Boost.MSM-eUML
> like library which compiles up to 60x quicker whilst being a slightly
> faster too?, click here
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4683016&code=a3J6eXN6dG9mQGp1c2lhay5uZXR8NDY4MzAxNnwtMTY0MTkzNTIwMA==>
> .
> NAML
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>
--
View this message in context: http://boost.2283326.n4.nabble.com/MSM-Is-there-any-interest-in-C-14-Boost-MSM-eUML-like-library-which-compiles-up-to-60x-quicker-whils-tp4683016p4683329.html
Sent from the Boost - Dev mailing list archive at Nabble.com.
_______________________________________________
> Le 08/02/2016 20:32, Kris a écrit :
>
> > On Sat, Feb 6, 2016 at 10:34 PM, Vicente Botet [via Boost] <
> > [hidden email] <http:///user/SendEmail.jtp?type=node&node=4683364&i=0>>
> wrote:
> >
> >> src + event [guard]/action = dst // guard throws runtime_error
> >> src + exception<runtime_error> = X // handle exception
> >> Yes, this is the idea.
> >
> > Great. I have improved error handling if it comes to exceptions.
> > Right now, if you do NOT compile with `-fno-exceptions` and do not
> specify
> > configure noexcept then you can handle any exceptions thrown on the
> > transition table.
> >
> > make_transition_table(
> > *"idle"_s + "event1"_t / [] { throw std::runtime_error{"error"}; }
> > , "idle"_s + "event2"_t / [] { throw 0; }
> >
> > , *"error_handling"_s + exception<std::runtime_error> / [] {
> std::cout <<
> > "exception caught" << std::endl; }
> > , "error_handling"_s + exception<> / [] { std::cout << "generic
> > exception caught, terminate..." << std::endl; } = X
> > );
> I missed the syntax for the orthogonal regions. It is not very explicit.
Well, you can make it more explicit if you wish by changing the syntax a bit
(*"idle"_s) + "event1"_t / [] { throw std::runtime_error{"error"}; }
, "idle"_s + "event2"_t / [] { throw 0; }
//---------------------------------------------------------------------------------------------------------/
, (*"error_handling"_s) + exception<std::runtime_error> / [] { }
> The idea to have an orthogonal section that does the error handling is
> good, but how would you do error recovery?
>
>
Well, it depends whether you have to or not recover out of it. If you
don't, another orthogonal region which will do the cleanup is good enough.
However, if you do have to recover I would use another state for it, as you
suggested.
make_transition_table(
(*"idle"_s) + "event1"_t / [] { throw std::runtime_error{"error"}; }
, "idle"_s + "event2"_t / [] { throw 0; }
, "idle"_s + exception<std::runtime_error> / [] { ... } = "recover"_s
, "recover"_s + "okay"_t = "idle"_s // fine now
);
> I don't think you should correlate whether MSM manage exceptions and
> whether the configure function is noexcept.
>
>
Why not? I find it better then being forced to setup some dummy type in the
state machine to enable exception handling.
Please notice that exceptions handling is enabled by default (unless you
compile with -fno-exceptions). The only reason why
noexcept with configure when you create a transition table counts its
because it will give you more performance.
> When you say " When guard/action throws an exception State Machine
> <<a href="
> http://boost-experimental.github.io/msm-lite/user_guide/index.html##sm-state-machine
> ">
> http://boost-experimental.github.io/msm-lite/user_guide/index.html##sm-state-machine>
>
> will stay in a current state.", do you mean that if there is an
> exception in the action part, the state will be the nesting state of the
> transition, as the exit of the source state will already be executed? If
> yes, this is not a leaf state, this is why I added a pseudo-state, to
> ensure a leaf state.
>
It means that if exception won't be handled and that source state will
remains the current state.
Exit of the source state won't happen in such case too. Change the state
happens
after guards/actions were executed properly, otherwise source state is
still a current state.
src_state + event [ guard ] / action = dst_state
^
|
1. src_state + on_exit
2. dst_state + on_entry
>
> > You can handle specific type of the exception(exception<type>) or just
> > any(exception<>).
> What would be the event associated to the action in this cases?
>
>
Simply, none. It won't compile when you try to add action/guard with the
event for this transition.
In case of exception<>:
auto guard = [] (auto event) {} // won't compile
auto guard = [] () {} // okay
However, you can get some info about the exception using
std::current_exception
auto action = [] () {
auto exptr = std::current_exception();
...
}
>
> >>> Okay, well, msm-lite doesn't support that as a feature. However, you
> can
> >>> achieve more or less all of mentioned things just by using C++.
> >>> For example, you can extend transiton table of a state machine by
> >> joining
> >>> it with another one.
> >>>
> >>> auto table1 = make_transition_table(transitions...);
> >>> auto table2 = make_transition_table(table1, other_transitions...);
> >>>
> >> This should respond to point 1*. 2* should need to replace the refined
> >> state in table1.
> >> Point 3 would covered if the make_transition_table function overrides
> >> the redefined transitions.
> >>
> > I was wondering whether your point with extending transitions can't be
> > achieved using sub machines instead ?
> This is another mechanism of extension that of course should work also,
> but that is not related to the previous 5 extensions mechanisms
>
> >> It would be great if you show how the user can address these points
> with
> >> your library using some run-able concrete examples.
> >>
> > Yea, I will work on that. Cheers for the pointers.
> >
> >
> Thanks for working on this.
>
Np
> Vicente
>
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>
>
> ------------------------------
> If you reply to this email, your message will be added to the discussion
> below:
>
> To unsubscribe from [MSM] Is there any interest in C++14 Boost.MSM-eUML
> like library which compiles up to 60x quicker whilst being a slightly
> faster too?, click here
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4683016&code=a3J6eXN6dG9mQGp1c2lhay5uZXR8NDY4MzAxNnwtMTY0MTkzNTIwMA==>
> .
> NAML
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>
--
View this message in context: http://boost.2283326.n4.nabble.com/MSM-Is-there-any-interest-in-C-14-Boost-MSM-eUML-like-library-which-compiles-up-to-60x-quicker-whils-tp4683016p4683369.html
Sent from the Boost - Dev mailing list archive at Nabble.com.
_______________________________________________
2,3,4 are executed only if the ward is true.
>>> You can handle specific type of the exception(exception<type>) or just
>>> any(exception<>).
>> What would be the event associated to the action in this cases?
>>
>>
> Simply, none. It won't compile when you try to add action/guard with the
> event for this transition.
> In case of exception<>:
>
> auto guard = [] (auto event) {} // won't compile
> auto guard = [] () {} // okay
>
> However, you can get some info about the exception using
> std::current_exception
>
> auto action = [] () {
> auto exptr = std::current_exception();
> ...
> }
>
>
Yes this should work.
> Le 09/02/2016 21:19, Kris a écrit :
>
>> On Tue, Feb 9, 2016 at 5:13 PM, Vicente Botet [via Boost] <
>> ml-node+s2283...@n4.nabble.com> wrote:
>>
>> Le 08/02/2016 20:32, Kris a écrit :
>>>
>>> On Sat, Feb 6, 2016 at 10:34 PM, Vicente Botet [via Boost] <
>>>> [hidden email] <http:///user/SendEmail.jtp?type=node&node=4683364&i=0>>
>>>>
>>> wrote:
>>> I don't think you should correlate whether MSM manage exceptions and
>>> whether the configure function is noexcept.
>>>
>>>
>>> Why not? I find it better then being forced to setup some dummy type in
>> the
>> state machine to enable exception handling.
>> Please notice that exceptions handling is enabled by default (unless you
>> compile with -fno-exceptions). The only reason why
>> noexcept with configure when you create a transition table counts its
>> because it will give you more performance.
>>
> Why do you want to loss this performance when you want exceptions enabled?
> Couldn't the configure function be always noexcept?
>
>>
>>
It's the opposite, I don't want to lose performance at any time. Exceptions
handling cause a bit of overhead as you have to be in try { ... } catch
statement.
Well, C++ defines noexcept and that's a default, how would you like to mark
that transition table can throw otherwise?. For example, noexcept(false)
seems a bit silly to use.
We don't have 'except' and therefore default behavior supports exceptions
unless you disable them via compiler flag.
I think UML doesn't specify the order when any of these should happen. At
least I'm not aware of it, but I might be wrong?
Anyway, defining it the following way
1 guard
2 action
3 src_state exit
4 change state
5 dst_state entry
may things much easier to handle from programming perspective. One doesn't
have to deal with undefined states .
Just for the record, Boost.MSM has a policy to set when change state should
happen.
I don't have a link to the UML recommendation, but the wiki agrees with
my order.
https://en.wikipedia.org/wiki/UML_state_machine#Transition_execution_sequence
> One doesn't
> have to deal with undefined states .
Well, as I said before, you must consider that there is a TOP state
associated to a SM. When you have a transition from S1 to S2, the action
is executed in the context of the TOP state.
I'm not saying that exit/action is better than action/exit, but if UML
defines the order exit/action I will see why before changing the semantics.
> Just for the record, Boost.MSM has a policy to set when change state should
> happen.
I wonder what was the rationale for this possibility. What
Boost.Statechart does?
Best,
Yea, I do get your point but IMHO when you look at transition table
(make_transion_table) and you see that configure function is noexcept it's
quite easy to get what is going on, but again, it's just my opinion.
I tried different approach before, when I was checking all guards/actions
whether they are noexcept or not. The problem with this solution was that
lambdas expression are usually written without the noexcept
and, since the state machine was behaving the same, it was hard to notice
that performance went done. All in all, I just like the idea of using
facilities provided by the standard here. I know it's not exactly what
one may expect as configure will never throw or be/should called by the
user.
Yea, it seems like. It's easier to handle exceptions this way, however,
being compliant with the UML is important.
I may change the order then as it will save me time in the future
explaining why it was done the other way ;)
Thanks for pointing that out.
>
>
> One doesn't
>> have to deal with undefined states .
>>
> Well, as I said before, you must consider that there is a TOP state
> associated to a SM. When you have a transition from S1 to S2, the action is
> executed in the context of the TOP state.
> I'm not saying that exit/action is better than action/exit, but if UML
> defines the order exit/action I will see why before changing the semantics.
>
> Just for the record, Boost.MSM has a policy to set when change state should
>> happen.
>>
> I wonder what was the rationale for this possibility. What
> Boost.Statechart does?
>
No idea what Statechart does. MSM rationale is here ->
http://www.boost.org/doc/libs/1_57_0/libs/msm/doc/HTML/ch03s05.html#d0e2714
BTW. I have a question related to local transitions. Concept seems to be
nice but I don't undesrtand why exit/entry is NOT triggered only 'if the
main target state is a substate of the main source'.
Why this concept can't be more general? Wouldn't that be nice?
s1 + e1 = s2 // exit from s1 / entry to s2
s1 ^ e1 = s2 // no exit from s1 / no entry to s2
I checked UML2.5 specification and I have found "Transition execution
sequence" (14.2.3.9.6 / page 316).
However, there is no much info about the sequence there. It's mostly about
that exit of the main state has to happen before entry to the target state.
I can't find anything about when guard/action should happen in the sequence
:/ buy it's a long document so maybe it might be found somewhere?
>
> BTW. I have a question related to local transitions. Concept seems to be
>> nice but I don't undesrtand why exit/entry is NOT triggered only 'if the
>> main target state is a substate of the main source'.
>> Why this concept can't be more general? Wouldn't that be nice?
>>
>> s1 + e1 = s2 // exit from s1 / entry to s2
>> s1 ^ e1 = s2 // no exit from s1 / no entry to s2
>>
>>
>> A local transition will ensure that there is no exit on s1, but there
> should be an entry in s2 if s2 is not s1.
> You will need to have a nested examples to see the difference between an
> external and a local transition.
Yea, I do get it. Cheers. Do have any example when local transitions are
useful? I see some usage for them but I struggle really to find a really
good use case for them.
xS11; t1; xS1; t2; eT1; eT11; t3; eT111
Where xAAA means exit action on state AAA and eAAA entry on state AAA.
ti are actions on the segmented transitions.
Just before this example you can find
*"Transition execution sequence **
*Every Transition, except for internal and local Transitions, causes
exiting of a source State, and entering of the target State. These two
States, which may be composite, are designated as the main source and
the main target of a Transition respectively.
The main source is a direct substate of the Region that contains the
source States, and the main target is the substate of the Region that
contains the target States.
NOTE. A Transition from one Region to another in the same immediate
enclosing composite State is not allowed. Once a Transition is enabled
and is selected to fire, the following steps are carried out in order:
1. Starting with the main source State, the States that contain the main
source State are exited according to the rules of State exit (or,
composite State exit if the main source State is nested) as described
earlier.
2. The series of State exits continues until the first Region that
contains, directly or indirectly, both the main source and main target
states is reached. The Region that contains both the main source and
main target states is called their least common ancestor. At that point,
the effect Behavior of the Transition that connects the
sub-configuration of source States to the sub-configuration of target
States is executed. (A “sub-configuration” here refers to that subset of
a full state configuration contained within the least common ancestor
Region.)
3. The configuration of States containing the main target State is
entered, starting with the outermost State in the least common ancestor
Region that contains the main target State. The execution of Behaviors
follows the rules of State entry (or composite State entry) described
earlier. "
I believe this is clear enough.
1 exits
2 action
3 entries
>> BTW. I have a question related to local transitions. Concept seems to be
>>> nice but I don't undesrtand why exit/entry is NOT triggered only 'if the
>>> main target state is a substate of the main source'.
>>> Why this concept can't be more general? Wouldn't that be nice?
>>>
>>> s1 + e1 = s2 // exit from s1 / entry to s2
>>> s1 ^ e1 = s2 // no exit from s1 / no entry to s2
>>>
>>>
>>> A local transition will ensure that there is no exit on s1, but there
>> should be an entry in s2 if s2 is not s1.
>> You will need to have a nested examples to see the difference between an
>> external and a local transition.
>
> Yea, I do get it. Cheers. Do have any example when local transitions are
> useful? I see some usage for them but I struggle really to find a really
> good use case for them.
>
>
>
Let say that you have a state S with two sub-states S1 and S2.
While in state S, if you receive the event E1 you want to go to S1, but
don't want to execute the exit of state S. However you want to execute
the exit of S1 or S2.
S ^ E1 = S1;
Think of E1 as an event that interrupts whatever you were doing on S1 or S2.
For me it is semi clear, but I do agree with your conclusion though.
However, there is no info about guards being executed before src state exit.
It might be implied by the statement that transition has to be enabled, but
I'm not sure about it.
>
>
> BTW. I have a question related to local transitions. Concept seems to be
>>>
>>>> nice but I don't undesrtand why exit/entry is NOT triggered only 'if the
>>>> main target state is a substate of the main source'.
>>>> Why this concept can't be more general? Wouldn't that be nice?
>>>>
>>>> s1 + e1 = s2 // exit from s1 / entry to s2
>>>> s1 ^ e1 = s2 // no exit from s1 / no entry to s2
>>>>
>>>>
>>>> A local transition will ensure that there is no exit on s1, but there
>>>>
>>> should be an entry in s2 if s2 is not s1.
>>> You will need to have a nested examples to see the difference between an
>>> external and a local transition.
>>>
>>
>> Yea, I do get it. Cheers. Do have any example when local transitions are
>> useful? I see some usage for them but I struggle really to find a really
>> good use case for them.
>>
>>
>>
>> Let say that you have a state S with two sub-states S1 and S2.
> While in state S, if you receive the event E1 you want to go to S1, but
> don't want to execute the exit of state S. However you want to execute the
> exit of S1 or S2.
>
> S ^ E1 = S1;
>
> Think of E1 as an event that interrupts whatever you were doing on S1 or
> S2.
>
>
Yea, yea I do get that. I was asking more about real life example. I mean,
what use case would require such behavior, because I can't think of any,
but I know there are some.
I'm asking because I don't have any experience with local transition and it
is hard to justify adding a new feature without a meaningful rationale.
Thank you for you feedback, it is very useful.
Yes, I believe that event reception and the guard evaluation are the enablers of the transition.
Let say that we are on a disabled state. In this state you have
sub-states representing the path to go to another enabled state (e.g.
requesting a password, ...) .
If you receive a reset event this would disable any trial to go to the
enabled state.
From the disabled state you could have a local transition when
receiving this reset event and go to the sub-state disabled/idle.
What is important is that you are always in the disabled state, so the
disabled exit has not been executed.
> Le 15/02/2016 11:08, Krzysztof Jusiak a écrit :
>
>> On Fri, Feb 12, 2016 at 6:44 PM, Vicente J. Botet Escriba <
>> vicent...@wanadoo.fr> wrote:
>>
>> Le 12/02/2016 12:20, Krzysztof Jusiak a écrit :
>>>
>>>
>> For me it is semi clear, but I do agree with your conclusion though.
>> However, there is no info about guards being executed before src state
>> exit.
>> It might be implied by the statement that transition has to be enabled,
>> but
>> I'm not sure about it.
>>
>>
> Yes, I believe that event reception and the guard evaluation are the
> enablers of the transition.
>
>
Yea, but that would mean that guard has to be evaluated before exit of the
state or any action, so the order would be.
1. guard [to enable transition]
2. exit src state
3. actions...
4. entry dst state
When the actual state change should happen in above sequence it's not
stated in the document as well.
I would assume following order according to the spec + a bit of rationality?
1. guard [to enable transition]
2. exit src state
3. actions...
4. CHANGE THE STATE TO DST HERE?
5. entry dst state
Cheers, it helps a lot.
> Le 16/02/2016 17:44, Krzysztof Jusiak a écrit :
>
> > Yea, but that would mean that guard has to be evaluated before exit of
> the
> > state or any action, so the order would be.
> >
> > 1. guard [to enable transition]
> > 2. exit src state
> > 3. actions...
> > 4. entry dst state
> >
> > When the actual state change should happen in above sequence it's not
> > stated in the document as well.
> >
> > I would assume following order according to the spec + a bit of
> rationality?
> >
> > 1. guard [to enable transition]
> > 2. exit src state
> > 3. actions...
> > 4. CHANGE THE STATE TO DST HERE?
> > 5. entry dst state
> >
> I agree. It was evident to me, but I can not point to any wording.
>
Great to hear that. However, above sequence makes exception handling a bit
harder as
with guards we haven't left the src state but with actions we started the
exit already.
1. When exception happens in a guard
* src state is unchanged
2. When exception happens in an action
* src state is exited
Moreover, following below sequence
3. actions...
4. CHANGE THE STATE TO DST HERE?
makes it harder to process internal events
"src"_s + event / process_event(other_event) = "dst"_s
, "src"_s + other_event = X // most likely, should be this one as we
haven't changed the state yet?
, "dst"_s + other_event = X
and, therefore, maybe it's better to have it the other way around?
3. CHANGE THE STATE TO DST HERE?
4. actions...
Vicente
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>
> ------------------------------
> If you reply to this email, your message will be added to the discussion
> below:
>
> To unsubscribe from [MSM] Is there any interest in C++14 Boost.MSM-eUML
> like library which compiles up to 60x quicker whilst being a slightly
> faster too?, click here
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4683016&code=a3J6eXN6dG9mQGp1c2lhay5uZXR8NDY4MzAxNnwtMTY0MTkzNTIwMA==>
> .
> NAML
> <http://boost.2283326.n4.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>
--
View this message in context: http://boost.2283326.n4.nabble.com/MSM-Is-there-any-interest-in-C-14-Boost-MSM-eUML-like-library-which-compiles-up-to-60x-quicker-whils-tp4683016p4683585.html
Sent from the Boost - Dev mailing list archive at Nabble.com.
_______________________________________________
I have never used process_event in an action on the same state machine
(You are re-entering the state machine :( ). The single think you can do
is to post it (push in a queue) or call process_event in another state
machine. However you must ensure the there are no cycles. The
asynchronous way avoids always the possible cycles.
In some projects I have defined a hierarchy of state machines and the
upper layer state machines use synchronous communication to communicate
to lower state machines and the reverse, lower layer use always
asynchronous communication with upper layer state machines (half
sync/half async).
There are 3 features that I'm missing in UML state machines that I found
in SDL [1]. Maybe these features have no sense with synchronous state
machines.
* Procedures that can contain states. The difference with nested states
is that procedures are stack based and return to the point of call when
the procedure terminates. You can reuse a procedure inside a state
machine several times of course.
* Synchronous Remote Procedures that allows to do a call/replay at once.
This avoids the use of wait states on which the every other event tan
the replay is deferred.
* Synchronous Remote Variables that allows to read a remote variable.The
same here; but just to query for the value of a remote variable.
Vicente
[1]
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&cad=rja&uact=8&ved=0ahUKEwi1vqWwqP_KAhUGWhoKHa-DB3oQFghEMAQ&url=http%3A%2F%2Fwww.itu.int%2FITU-T%2Fstudygroups%2Fcom10%2Flanguages%2FZ.100_1199.pdf&usg=AFQjCNFwOMg8j5RuW77nxtjPuj3c8eq2mQ&sig2=svSxdC5kgb1EBGDbnchYwg
[2] https://fr.wikipedia.org/wiki/Specification_and_Description_Language
It's a great point! To be honest with you, I have never liked process_event
on the transition table, however, I blindly followed MSM approach (fsm is
always passed to guards/actions in MSM, so you can do whatever) but it's a
bit dangerous here, as you mentioned. I'm going to change that to support
only defer or queue events on the transition table. Thanks for your input
on that, makes complete sense.
>
> In some projects I have defined a hierarchy of state machines and the
> upper layer state machines use synchronous communication to communicate to
> lower state machines and the reverse, lower layer use always asynchronous
> communication with upper layer state machines (half sync/half async).
> There are 3 features that I'm missing in UML state machines that I found
> in SDL [1]. Maybe these features have no sense with synchronous state
> machines.
>
> * Procedures that can contain states. The difference with nested states is
> that procedures are stack based and return to the point of call when the
> procedure terminates. You can reuse a procedure inside a state machine
> several times of course.
> * Synchronous Remote Procedures that allows to do a call/replay at once.
> This avoids the use of wait states on which the every other event tan the
> replay is deferred.
> * Synchronous Remote Variables that allows to read a remote variable.The
> same here; but just to query for the value of a remote variable.
>
> Thanks for the links. I have never seen SDL before, it looks really
interesting. A lot of new concepts for me. I know that, Christophe (author
of MSM) was working on asynchronous library and integration it with MSM,
however, I'm not sure about the status. Anyway, it's a good learning to
follow. Cheers for that. Definitely a lot of stuff to implement in the
future!