[IGSTK-Developers] State machine questions

David Gobbi dgobbi at atamai.com
Wed Aug 24 15:59:15 EDT 2005


Kevin Gary wrote:

> Hi all,
>
> I was looking at some of the state machine code to get
> refreshed on the topic, and as often happens when I look
> at code, I got confused ;).

Confusion is to be applauded.  It is a sure sign that lots
of critical thought is being applied ;)

> In looking at SerialCommunication and base Tracker
> classes, the sequence of calls for the Open methods
> will first push an input to the SM and then process it.
> In StateMachine::ProcessInputs, the function pointer is
> traversed (toward the bottom of the method), and the
> ensuing private method on the original object called.
> The result of traversing the transition should leave
> us in an "AttemptingToDoSomething" state. The private
> method invoked (SerialCommunication::AttemptToOpenPort
> or Tracker:: AttemptToOpen) then does a PushInputBoolean
> based on the result of a virtual "InternalXXX" method call.
>
> Some questions:
>
> 1. I do not see a call to StateMachine::ProcessInput(s)
> anywhere after the PushInputBoolean (which queues an input
> to the SM based on the outcome of the Internal method).
> When is the queued input processed? Subsequent call to
> the SM on the next request?

At the time when PushInputBoolean() is called, we are already
inside ProcessInputs().

The process is as follows: someone pushes a "DoSomethingInput",
and then calls ProccessInputs().  Then ProcessInputs() calls
the AttemptToDoSomething() method, which calls
PushInputBoolean() to push the next input (a success or failure input).
When the AttemptToDoSomething() method returns, ProcessInputs()
will set the state to the AttemptToDoSomething() state, and will then
proceed to process the "success" or "failure" inputs that have been
added to the input queue.

If that sounds convoluted to you, you will probably be glad to hear
that it sounds convoluted to me, too.  I am hoping that the state
machine processing can be simplified, and I hint at this at the
end of the "Exceptions and State Machines" section of the
"State Machines" wiki page.

> 2. At the end of StateMachine::ProcessInput, the last 2
> things done are 1) an execution of the transition, i.e.
> the function pointer, and 2) setting the state of the
> SM itself to the endpoint of the transition. If the
> invocation of the function pointer itself leads to a
> transition, then the call sequence will in fact "nest"
> the invocation, meaning you will not end up in the
> correct state. For example, in my hand-trace, it would
> seem the SerialCommunication object would end up in the
> "AttemptingToOpen" state and not one of the "m_IdleState"
> (on failure) or "m_PortOpenState" on success. Of course,
> question #1 may make this moot as I do not see when we
> would ever traverse the 2nd transition (it seems to me
> the only reason it works is because the Internal method
> does the actual work *before* the PushInputBoolean call,
> e.g. not under the guide of the StateMachine).

The current state machine design will break if ProcessInput()
is ever called from within itself, for exactly the reason you
cite. 

The reason things are working right now is hopefully
addressed in my answer to your first question.

> 3. I am not sure of the utility of multiple queued inputs
> to our StateMachines. As each input is mapped onto a single
> transition in a given state, and the processing of a single
> input should lead to a new target state, it seems that
> a sequence of inputs queued on the basis of being in some
> state will find the SM will not be in that source state
> when the input is actually processed! For example, assume
> I have a SM with 3 states, S1-S4, and 3 inputs I1-I3. S1
> accepts inputs I1 and I2. I1 leads to a transition to S2,
> I2 leads to a transition to S3. If I queue I1 and I2 and
> then call ProcessInputs, I will have queued I2 believing
> my object was in S1, when in fact it will be in S2 when
> I2 is processed???

I think that the only reason for the queued inputs was to
get around the problem you described in question 1
(that is, so that we wouldn't set a new input before
we had reached the state where we could process
that input).

> 4. I am not sure of the utility of having the StateMachine
> traverse two transitions and go through two states in this
> call pattern. As we are assumed single-threaded (right?)
> and these are private calls where the result of the original
> client method invocation will never seemingly result in
> being in the "AttemptingXXX" state...why introduce the
> complexity? I'm not sure I see the benefit?

You are correct, the state machine will both enter and leave
the "attempting" state within a single invocation of an
interface function.

> I also looked at the ImageSpatialObjectRepresentation, and
> it does not do the "Attempting" type pattern, and so these
> questions disappear (though it does validate input up
> front to determine the input to push, instead of doing the
> PushInputBoolean thing).

There is a difference between validating an input, and
validating a result.  With the former, you do the check
before you do any processing, with the latter, you need
to do some processing first before you know what
the next step is.

The way things work now, is that a state machine input
will cause an Attempt() function to be called, which
will then do some processing and then set the next
input.

You are asking why we can't just call the Attempt()
method directly, an hence eliminate both the
Attempt input and the Attempt state.

I'll have to think about this, but you might be right,
maybe we can eliminate them.  Also, if we eliminate
the Attempt states then we no longer need to set
Success inputs.  We can just call the input that will
cascade us up into whatever state we're supposed
to get to if we are successful.

But then, if we need to do processing in order to
get into that next state, and an error occurs during
that processing... I'll need to think a bit more.

Obviously the "AttemptState" approach works.
The big question, though, is whether there is a
better way to do things.

> Sorry for the long narrative, it is involved code to trace
> through by hand. I'm sure I am missing something...

The narrative is very much appreciated. You make
some excellent points.  I hope that I managed to
answer at least some of your questions.

 - David

> Hope everyone has been well...

>
> K2
>
>
>
> _______________________________________________
> IGSTK-Developers mailing list
> IGSTK-Developers at public.kitware.com
> http://public.kitware.com/cgi-bin/mailman/listinfo/igstk-developers
>




More information about the IGSTK-Developers mailing list