[statechart] How to keep transition actions separated from the interface?

Hi,
I am implementing a fsm for a kind of a project class, which tracks certain
changes like adding special files or starting a computation. To keep the
interface as small/clean as possible all interactions with the fsm should be
soley processed by the process_event method.
But seemingl I have to declare transition actions public in an outer state to
make them available for inner state reactions/transitions. Is there any nice
way to avoid this and to keep transition actions separated from the public
interface? (Declaring *all* inner states which need access to be friend seems
too ugly to me...)
A small code snippet to demonstrate my issue:
In Project.h:
struct Idle;
struct Project : sc::state_machine< Project, Idle >
{
public:
//....
void solve(const EvSolve &);
//...
};
//...
struct Idle : sc::simple_state< Idle, Project, mpl::list

Hi Andre
I am implementing a fsm for a kind of a project class, which tracks certain changes like adding special files or starting a computation. To keep the interface as small/clean as possible all interactions with the fsm should be soley processed by the process_event method. But seemingl I have to declare transition actions public in an outer state to make them available for inner state reactions/transitions. Is there any nice way to avoid this and to keep transition actions separated from the public interface? (Declaring *all* inner states which need access to be friend seems too ugly to me...) [snip code]
Have you read http://www.boost.org/doc/libs/1_35_0/libs/statechart/doc/faq.html#HideInnerW...? Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.

Hi Andreas, On 2008-04-06, Andreas Huber wrote :
Hi Andre
I am implementing a fsm for a kind of a project class, which tracks certain changes like adding special files or starting a computation. To keep the interface as small/clean as possible all interactions with the fsm should be soley processed by the process_event method. But seemingl I have to declare transition actions public in an outer state to make them available for inner state reactions/transitions. Is there any nice way to avoid this and to keep transition actions separated from the public interface? (Declaring *all* inner states which need access to be friend seems too ugly to me...)
[snip code]
Have you read <http://www.boost.org/doc/libs/1_35_0/libs/statechart/doc/faq.html#HideInne rWorkings>?
Yes, I read it before but so far I haven't been able to link this to my problem. Unfortunately it's not clear to me how the faq answer can be applied to give an inner state reaction access to an outer state transit function without declaring the latter to be public. I am not that much C++ matured, so maybe I am overlooking the obvious solution? (In that case, please forgive my ignorance :-)) Regards, Andre

"Andre Massing"
Have you read <http://www.boost.org/doc/libs/1_35_0/libs/statechart/doc/faq.html#HideInne rWorkings>?
Yes, I read it before but so far I haven't been able to link this to my problem. Unfortunately it's not clear to me how the faq answer can be applied to give an inner state reaction access to an outer state transit function without declaring the latter to be public.
Sorry, I misread your original post. Indeed, the FAQ item does not apply to your problem. I can't think of any good way how you could declare transition actions non-public. I'm wondering why you'd want to do so? If you have applied the pattern described in the FAQ item, FSM clients will never see any of the state classes with the public transition actions, right? Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.

Hi, On 2008-04-07, Andreas Huber wrote :
Have you read <http://www.boost.org/doc/libs/1_35_0/libs/statechart/doc/faq.html#HideI nne rWorkings>?
Yes, I read it before but so far I haven't been able to link this to my problem. Unfortunately it's not clear to me how the faq answer can be applied to give an inner state reaction access to an outer state transit function without declaring the latter to be public.
Sorry, I misread your original post. Indeed, the FAQ item does not apply to your problem. I can't think of any good way how you could declare transition actions non-public. I'm wondering why you'd want to do so? If you have applied the pattern described in the FAQ item, FSM clients will never see any of the state classes with the public transition actions, right?
Hmm, sorry, but this point is still not clear to me. Using this pattern, what keeps the client from directly using a public transit function in the fsm? To enforce capsulation of the inner work, the client should only be able to invoke the fsm by events, not by anything else. Probably I am missing the point, but as I said I am not a C++ master at all. Regards and thanks for the fast replies! Andre

Andre Massing
Sorry, I misread your original post. Indeed, the FAQ item does not apply to your problem. I can't think of any good way how you could declare transition actions non-public. I'm wondering why you'd want to do so? If you have applied the pattern described in the FAQ item, FSM clients will never see any of the state classes with the public transition actions, right?
Hmm, sorry, but this point is still not clear to me. Using this pattern, what keeps the client from directly using a public transit function in the fsm?
The fact that transition actions are members of simple_state<> subclasses. If you apply the pattern outlined in the FAQ item, none of these classes are visible to FSM clients. Looking at <http://www.boost.org/doc/libs/1_35_0/libs/statechart/doc/faq.html#HideInnerW... ings> you see that a client including StopWatch.hpp has *no* *clue* of the existence Running and Stopped classes. The client does know about the existence of the Active class but since it is only forward-declared, he does not have access to its member functions. Now, if you add a transition action for say the transition from Running to Stopped, you'd add a member function to the Active class in StopWatch.cpp, right? Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.

Hi again, On Monday, 7. April 2008 12:26:18 Andreas Huber wrote:
Hmm, sorry, but this point is still not clear to me. Using this pattern, what keeps the client from directly using a public transit function in the fsm?
The fact that transition actions are members of simple_state<> subclasses.
I see, that's the point. When I posted my question I had the second example of http://www.boost.org/doc/libs/1_35_0/libs/statechart/doc/tutorial.html#Trans... in mind, where the transition function DisplayFocused is a public method of the struct Camera sc: state_machine< Camera, NotShooting > . But introducing an outermost context (say Active :-)) which all substates have in common and moving state_machine transit functions there should be the right approach, shouldn't be? Thanks for your help and the detailed explanation! Regards, Andre

But introducing an outermost context (say Active ) which all substates have in common and moving state_machine transit functions there should be the right approach, shouldn't be?
Right. Keep in mind though, that state_machine<> declares other functions you might want to hide too: <http://www.boost.org/doc/libs/1_35_0/libs/statechart/doc/reference.html#Clas... mplatestate_machine>, e.g. state_begin(), state_end(), etc. That's why you often don't expose state_machine<> subclasses directly but wrap them in another object. Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.

The fact that transition actions are members of simple_state<> subclasses. If > you apply the pattern outlined in the FAQ item, none of these classes are > visible to FSM clients. Looking at> > http://www.boost.org/doc/libs/1_35_0/libs/statechart/doc/faq.html#HideInnerW... Is it possible to apply this apporoach to the asynchronous_state_machine? For some reasone, trying to do so in my program causes compiler error: "use of undefined type 'Active'". Probably, I've done something wrong, but I'd like to know if it should work theoretically, before I turn my code upside down :). Thanks!
Connect to the next generation of MSN Messenger http://imagine-msn.com/messenger/launch80/default.aspx?locale=en-us&source=wlmailtagline

Hi Igor
The fact that transition actions are members of simple_state<> subclasses. If you apply the pattern outlined in the FAQ item, none of these classes are visible to FSM clients. Looking at
http://www.boost.org/doc/libs/1_35_0/libs/statechart/doc/faq.html#HideInnerW...
Is it possible to apply this apporoach to the asynchronous_state_machine?
Yes, but not in exactly the same way.
For some reasone, trying to do so in my program causes compiler error: "use of undefined type 'Active'". Probably, I've done something wrong, but I'd like to know if it should work theoretically, before I turn my code upside down :).
In your asynchronous_state_machine<> subclass hpp file add the following line : private: // ... virtual void initiate_impl(); In your asynchronous_state_machine<> subclass cpp file add the following lines: void YourClassName::initiate_impl() { machine_base::initiate(); } Please let me know whether that works for you. Thanks & Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.

Thanks a lot! I will try this on Sunday, and report here.> In your asynchronous_state_machine<> subclass hpp file add the following > line :> > private:> // ...> virtual void initiate_impl();> > In your asynchronous_state_machine<> subclass cpp file add the following > lines:> > void YourClassName::initiate_impl()> {> machine_base::initiate();> }> > Please let me know whether that works for you.> > Thanks & Regards,> > -- > Andreas Huber _________________________________________________________________ News, entertainment and everything you care about at Live.com. Get it now! http://www.live.com/getstarted.aspx

Hi Andreas, Unfortunately, it still produces compile-time error for the same reason... The error occures when void state_machine::initial_construct() is being compiled, since the InitialState is not defined yet. Probably you've got some example that compiles for sure? Thank you, Igor'.
In your asynchronous_state_machine<> subclass hpp file add the following > line :> > private:> // ...> virtual void initiate_impl();> > In your asynchronous_state_machine<> subclass cpp file add the following > lines:> > void YourClassName::initiate_impl()> {> machine_base::initiate();> }> > Please let me know whether that works for you.> > Thanks & Regards,> > -- > Andreas Huber
Explore the seven wonders of the world http://search.msn.com/results.aspx?q=7+wonders+world&mkt=en-US&form=QBRE

Hi Igor
Unfortunately, it still produces compile-time error for the same reason... The error occures when void state_machine::initial_construct() is being compiled, since the InitialState is not defined yet.
Sorry, my bad. I forgot to mention that you need to add a class member specialization as well, right after the declaration of your FSM: template<> void sc::asynchronous_state_machine< YourClassName, YourInitialStateName >::initiate_impl() {}
Probably you've got some example that compiles for sure?
Yes, please see the changed PingPong example in the SVN trunk. Verified with VC++ 9.0. HTH & Regards, Andreas -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.

Sorry, my bad. I forgot to mention that you need to add a class member > specialization as well, right after the declaration of your FSM:> > template<> void sc::asynchronous_state_machine<> YourClassName, YourInitialStateName >::initiate_impl() {}> Ok, now it's almost ok :). One minor issue is that machine_base is a private typedef, so I substituted it by the explicit type:
void MyClassName::initiate_impl(){ state_machine

Hi,
template<>> void sc::asynchronous_state_machine<> YourClassName, YourInitialStateName >::initiate_impl() {}
Now I try to define and test some "contents" of my FSM, and for some reason it doesn't work so far...
The 1st problem is that in_state_reaction(s) are not triggered. The machine enters some inner state, then EvMyEvent1 is posted by the machine creator. The in_state_reactions are defined at the outermost level - in MyMachine itself. IIUC, any event that has no reaction in a current state, is forwarded to the outer one, right? So the foolowing definition should be ok:
class MyMachine : public sc::asynchronous_state_machine

However, doSomething() functions are not called, and I even can't put there breakpoint (dropped out by the linker?). It I define them in cpp, the breakpoints can be set, but the functions are not called anyway...
Any idea would be appreciated!
The reactions typedef cannot appear in the state_machine itself. It must be in a state. The PingPong example should get you started. Regards, Andreas

...I forgot to say that I'm using VC++8.0 and boost 1.34.1
In your asynchronous_state_machine<> subclass hpp file add the following > line :> > private:> // ...> virtual void initiate_impl();> > In your asynchronous_state_machine<> subclass cpp file add the following > lines:> > void YourClassName::initiate_impl()> {> machine_base::initiate();> }> > Please let me know whether that works for you.> > Thanks & Regards,> > -- > Andreas Huber
Connect to the next generation of MSN Messenger http://imagine-msn.com/messenger/launch80/default.aspx?locale=en-us&source=wlmailtagline
participants (3)
-
Andre Massing
-
Andreas Huber
-
Igor R.