
On 8/10/09 12:48 AM, Andreas Huber wrote:
The machine is effectively a timer and wraps another internal timer class that can be stopped/started and suspended/resumed. This is all the machine does. The internal timer class can get/set its interval and can also get/set a delegate, that is called (if set) when the timer fires. These internal timer management interfaces are "passed through" to the state machine interface, such that application/test code is as follows:
[snip code]
Where I have run into a problem is that my machine "pass through" setter methods allowing the delegate to be set or the timer interval to be changed (neither of which materially alter the state of the machine) cannot be called as they are non-const qualified whereas their corresponding getters work fine since they are const qualified.
So both the values of the delegate and the interval are orthogonal to the state the machine has? If so, I'm wondering why they're not members of struct Timer? This would make ITimerManagement unnecessary and also save quite a bit of code?
Andreas: Making the internal timer a member of the state_machine was precisely my initial implementation; however, initially, I'd found a destruction ordering problem with that approach. Basically, on destruction of the running state, I ensure the timer is stopped: struct Running : Interfaces::IRunning, Interfaces::ISuspended, state<Running, Active> { public: typedef mpl::list< transition<Events::Stop, Stopped>, transition<Events::Suspend, RunningSuspended> > reactions; Running(my_context inContext) : Interfaces::IRunning(true), Interfaces::ISuspended(false), my_base(inContext) { context<Machine::Timer>().Start(); } ~Running(void) { context<Machine::Timer>().Stop(); } }; Initially, the machine and, in turn, the internal timer object appeared to be destructed before the state, causing an assertion when I tried to stop the destructed object. There was also an assertion I had hit on construction of the running state: --> Implementation::States::Running::Running() Assertion failed: (get_pointer( stt.pContext_ ) != 0), function context_impl, file boost/statechart/simple_state.hpp, line 683. Abort On revisiting my current implementation, neither of these no longer appear to be the case. I now wrap the machine in another object and call .initiate/.terminate: SuspendableTimer(void) { mMachine.initiate(); } ~SuspendableTimer(void) { mMachine.terminate(); } This handles the destruction ordering correctly. Through iterating on the const state_cast issue, I had also revised the base of the Running state to 'state' rather than 'simple_state' which eliminated the construction assertion for that state. Thanks for the suggestion to revisit that implementation. The conditions had changed but I hadn't reinvestigated once the conditions changed.
What is the purpose of the IRunning & ISuspended structs?
They are application-level pseudo-state queries. Thanks for the tips! Regards, Grant