|
Boost Users : |
Subject: Re: [Boost-users] [statechart] Non-Const Machine Pass-throughs and state_cast
From: Grant Erickson (gerickson_at_[hidden])
Date: 2009-08-10 12:06:40
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
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net