Boost logo

Boost :

Subject: Re: [boost] [msm] Review
From: Christophe Henry (christophe.j.henry_at_[hidden])
Date: 2009-12-15 16:23:45


Hi Michael,

>I personally find this library both useful and well
>implemented for many of my needs. The documentation is
>lacking and must be extended to include a library
>reference. Additionally, I would like to see SimpleStates
>implemented to support internal transitions as called
>out in the standard. Other issues are detailed; however,
>do not affect my qualified vote of "acceptance". My
>conditional recommendation for acceptance (yes vote)
>is based on resolving the documentation issues and lack of
>SimpleState internal transitions.

Thank you for the detailed review. Your UML experience is very
valuable and appreciated.
I'd like to discuss a few points. I've been thinking about internal
transitions. I see 2 ways to implement them:
- an UML-conform way where states have their own stt with reduced rows
(no target)
- a row in the state machine stt (also without target) which I wanted
to implement anyway.

The first has the advantage of being UML-conform and thus respecting
the UML priority in case of conflicts (internal transitions having the
highest). It also makes the state more valuable and maybe reusable.
The second is more general than the UML-conform way as it allows you
to define yourself your priority according to the position of the
transition in the stt. It will also compile faster and be slightly
faster. You also see the conflict better in the stt. But you lose a
reuse possibility.
I understand why internal transitions have a higher priority in
submachines (for exit points to work I suppose) but for simple states?
That's why I personally tend to prefer solution 2 but I'm interested
in your take about it.

>I haven't thought too much about this, but it seems that the functor (Row)
>mechanism might be extended further to replace the various
>"arow" syntax completely.

It can do all what the "row" does, all in one. I would still prefer to
keep the "row"s because they are so simple that they attract
unexperienced users who are sometimes scared of seeing templated
functors (I tried ;-) ). They are a good entry point into MSM.

>I find myself missing choice points. Using "anonymous
>transitions" nearly allows the same semantic... but not quite.

For interest, what don't anonymous transitions allow? I scratched my
head for a long time and all I found was for the case where you have
multiple choice points. In this case, the path goes further only if at
least one full path to another state is found (if I got it right). Is
there another reason to have choice points?

>I also miss not having a "any" or "*" trigger
>definition. In essence, if no transition match is found for
>the active trigger ... take this transition.

This one was left out because I found no easy way to do it. It'd
probably involve adding behind the hood a row for every event of a
machine. It's harder to know how many rows are needed then. Besides, I
never found a use case for this, so if you have one, I'm quite
interested.

>Additionally, an example of converting a runtime int to
>a type is in order. Most people doing statemachine work are
>acting on some trigger that now needs to be translated to
>a data type. There are many ways to slice this but none are listed.

I unfortunately found not many ways and almost all are pretty bad. One
would be an ugly switch/case, the other guards (forcing a O(n)
dispatch). Probably the best is letting the action generate internally
another event.
I will look for a way to solve this better.

>As an aside, I would be happy to review and offer feedback
>with documentation modifications. I may be able to offer some
>assistance with modifications also.

With pleasure! As you see, I already started ;-)

>Inconsistent use of eUML. Sometimes it is EUML (particularly at the
>start of a sentence.) I believe it should always be eUML.

Being not a native speaker, I followed what Word told me and it was
probably a bad idea so I'll trust you on this.

>While the implementation of deferred events is correct according
>to UML I have found that the ROOM concept is extremely useful
>and have implemented it in my own libraries. You may want
>want to consider it as a feature to MSM

I admit I don't completely get it but it surely sounds interesting.
Would you have some written document or spec about it?

>Without a deep history concept in MSM I am required
>to specify a history policy for each contained sub-state machine
>(composite state). I do find this rather annoying though
>it is workable.

I find rather annoying the UML way. At least there should be a
workable solution for orthogonal regions and deep history. Yes, MSM
forces a policy but in exchange gives you much more power.

>My initial reaction to flags is "composite states already
>supply this information". I can see that flags can provide
>multiple slices of meta state information and *might* be
>useful. I am in general leery of abstractions that obfuscate
>additional state information. From a diagram POV, that
>state information is missing. In my world this typically
>means that the granularity of machines is wrong

Flags are a generalization of IS_IN for some UML tools. Consider the
following example:
State1 fulfills some property (called P1). State3 fulfills a property
P2. And State 2 fulfills P1+P2. Now, composite won't help you because
there is no way to put State2 in 2 composites. So when checking in a
guard for, say P1, you'll be left with if (IS_IN(State1) ||
IS_IN(State2)).
I personally prefer is_flag_active<P1>().
In this case, there is probably nothing wrong with your hierarchy,
it's simply the IS_IN concept which is not enough general.

>I personally like this format for describing a row. I hate
>to suggest yet one more mechanism... but having "row" utilize
>a "none" would be nice.

Yes, that there is no "none" is a limitation of having function
pointers in "row". Even having default value was making compilers
unhappy.
It was one of the reasons for having the "Row". OTOH function pointers
really can be understood by everybody (I work a lot with ex-C
developers).

>I find my fence riding odd because I have always thought a DSEL
>like this would be the cat's meow. I think it might be the
>copious use of BOOST_TYPEOF is just hard on my eyes and getting used
>to the ordering of build_state. All of those instantiations of objects
>with the ().... it just looks messy to me.

I'm open to any suggestion. The only other way I see is to create an
instance for each type used in the stt, but it's also not great. We
could pack it in a macro, but it hardly qualifies as more beautiful.
Could you try the new row grammar which I posted in the vault and tell
me if it looks slightly better? (note: sorry, I still use == instead
of =. This will be changed too).

>eUML seems to be a non-starter for me and these platforms.

I've been wondering about this too. VC makes a much better job at eUML
executable size (no size overhead), so it is possible and I hope g++
will catch back.

Thanks for the very useful comments.

Christophe


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