12 Apr
2012
12 Apr
'12
8:26 a.m.
Thanks a lot for your time and suggestions Christophe! > Let me see if I got it right. You want a timer to count from x to 0, and when timer == 0, generate a timeout event, correct? > Then you want the possibility to reset the timer. > IIUC, you implemented your timer as a second region with a single Timer state. This looks so far ok to me because the region can process events to the state machine (for other regions). > Of course, the more complicated your timer gets, the harder it becomes. You are totally right! :-) >> - A Timer inside all my (sub)state machines? > Sounds like a lot of work ;-) agree! ;-) >> - An independent state machine only for the Timer and (not so ugly) >> pointers from/to it in all my (sub) state machines? > This looks like a perfect use case for a submachine. Define it once as an independent state machine and reuse it in any state machine needing a timer. Yes! In my first approach i use only an independent and reusable "state" and not a complete "state machine", but my idea is what you say: independent and reusable! ;-)) > So far so good, but you are stuck with how to inform client state machines of your timer that there is a timeout, right? mmm... not exactly... In fact, the timeout is working fine. It is sent from the timer state/region and processed fine in the "main" machine/region, and in their submachines. Is the reset event (only when generated in a submachine of the main machine/region) which is really failing. The reset is always generated when there is "activity" in the main machine/region, where I (could) have submachines. If there is "activity" in a submachine, the reset event is generated in the submachine (but not up-fwd) and then is not processed by the timer region of the upper state machine... So, until now, the *reset in a submachine* is my real problem, not the timeout (which work great!). >> - More work on the pseudo exit? > - use the UML way. The timer is a state machine, with a pseudo exit when a timeout is detected. This is an encapsulated submodule used by any fsm. Like a well-behaved submodule, it advertises that timeout events are going to be fired through the pseudo exit. How it is done inside is not the outer fsm's business. Ok, iiuc, this is a better way to define that a timeout is going to be sent outside the state machine. And, although now the timeout is not a problem for me, i understand that pseudo-exit is the standard way to say "I'm a (full) state machine but I'm sending events out of me". is this correct? (i should read something about uml right now! ;-) Then I should probably use them (the pseudo exists) also for the resets generated in my submachines... I have to read more on pseudo exits... > This has several advantages: > - no ugly pointer > - UML-conform > - perfectly reusable and encapsulated timer for different uses. Often, fsm's need a timer but differ in how they handle timeouts. Leave it to them. The documentation states the timeout is sent through a pseudo exit. Or several pseudo exit states. > - the timer is a state machine in its own right, you can write a wonderful unit test for it alone. That's exactly what i'was looking for! :-)) But here I'm still missing my real problem: how to (say in the documentation and to) implement the fact that the timer can/should receive "reset" events from any (sub) state in the orthogonal region(s). May be pseudo-entries...? >> For this reason I could think that a (sub) state machine could handle >> some "no_transitions" for some events (some cached cases), but it can >> also auto-upper-fwd them to the parent state machine... > I understand but it's not the way the Standard is thought (well, at least I think). You're supposed to process an event on the outer, which then uses priority rules to know what's done (deeper first, completion events, deferred events, conflicts, etc.). I see, but iiuc the standard way is fine for me! I mean, iiuc, the key difference here between the standard and the msm is that in the standard all events are always processed by the outest sm (and then it uses the prioty rules), and in msm we can process events in the "submachine scope" (in fact, until now, if we hate ugly pointers, then we are forced to process events only in that submachine scope, right? ;-). Then, iiuc, if msm removes the possibility of processing events directly into submachines but the event processing is always done starting from the outer state machine, then everything should work (and be more standard-conform)? Am I missing something here? I mean, the upper-fwd is probably a kind of bad idea needed (or useful) only because msm allows (now it "forces") event processing directly in submachine scopes, if not, every thing should just work? If I'm right, then, I'm wondering if the processing of events directly in submachines is useful in some cases...? I mean, I see that access to the submachine can be useful if someone has some kind of "global" data members in it (shared by all the states) and want to access them... But the fact of event processing, is really useful in any case? Forcing the event processing to start always to the outest state machine should not remove any possibility we have now... or it will? I'm far to be sure, but now I'm thinking something like: sm::process_event(evt) { if(this->is_contained()) outer->process_event(evt); // assuming we have a pointer to the outer sm... else process_event_with_rules(evt); } ok, that's upper-fwd... ;-) Cheers! Albert