oomoore(n) 1.0.1 oomoore "Object Oriented Moore State Machine"

Name

oomoore - Moore State Models and Event Dispatch for TclOO

Table Of Contents

Synopsis

Description

This manpage describes the oomoore package which is a Tcl script extension that allows the specification and execution of Moore type state models that can be used as a base class for TclOO classes.

The oomoore package is an namespace ensemble command that defines as single subcommand, model. The ::oomoore::model object is a meta-class. Instances of the model class are configured by specifying the states and transitions. The resulting class is then typically used as a superclass that imbues the subclass with the defined state behavior.

The Moore type of state models associates actions with states and executes the action upon entry into a state. We define a state model to be the invariant definition of states, events and transitions. We define a state machine to be an instance of a state model that has an implicit state variable that holds its current state. All state machines behave independently of each other and all state machines that are instances of the same state model have the same set of states, events and transitions.

Once a state model is defined and a state machine is created, methods are used to signal events to state machines. Events may be delivered asynchronously or synchronously. In asynchronous event delivery, each state action completes before any other transitions are dispatched (i.e. the action exhibits run-to-completion behavior). Asynchronous delivery uses the Tcl event loop. Asynchronous delivery can also be delayed, in effect requesting the event to be delivered at some time in the future.

Synchronous event delivery causes an immediate dispatch of the event with the transition and state action executed like any regular procedure. Therefore, state actions may not be completed and complicated, cyclic synchronous event generation can cause undesired results. However for simple isolated state machines, synchronous delivery avoids the need to enter the Tcl event loop.

COMMANDS

The oomoore package defines a TclOO class that is intended to be used to define a superclass that has state behavior We divide the command descriptions into sections:

  1. Creating a state model class.

  2. Specifying the states and transitions of a state model.

  3. Methods of the state model class.

  4. Methods of state machine objects.

STATE MODEL CLASS COMMANDS

::oomoore model create smclass definition
::oomoore model new definition

The ::oomoore model is a TclOO meta-class that creates a state model class whose state behavior is specified by definition. The return value is a fully qualified state model class command name. The definition is evaluated in a context where the MODEL DEFINITION COMMANDS described below are available. The Model Defintiion Commands constitute a small language that is used to define the states, events and transitions of the state model. The returned smclass class has the methods listed below in the STATE MODEL METHODS section. Objects created from a state model have the methods listed below in the STATE MACHINE METHODS section.

MODEL DEFINITION COMMANDS

The definition argument to the ::oomoore model constructor is evaluated as a Tcl script. That script should invoke the following commands to define the properties of the state model. The order of invocation of these commands is arbitrary, i.e. it is not necessary to define all the states before the transitions.

state name arglist body

The state command defines a state of the model named, name. The formal parameters of the state are given by arglist in the style of the ::proc command and the state command is patterned after proc to show the close association of state action to transitioning into a state. When an event is received by a state machine instance of this state model and the transition causes name state to be entered, then body is executed with the arguments carried by the event. When body is invoked, it is invoked as a method and the usual facilities of a TclOO method are available.

transition currState - event -> newState

The transition command specifies the transition that a state machine is to make when it is in the currState state and it receives the event named, event. Receiving event while in currState causes the state machine to transition to newState and to execute the state action associated with newState. The currState must be a state defined, ultimately, by invoking the state command. The newState must be a defined state or one of the special non-transitioning states named IG or CH. If newState is IG, then the event is ignored and no transition takes place. If newState is CH, then the event is deemed logically not to be able to happen and this is logged as an error. It is also a corrollary to the way Moore machines are defined that any event that causes a transition into a given state must carry with it argument values that match the formal parameters of that state. Failure to do so will result in a run-time error.

Note that no separate command is provided to define event names. The set of events to which a state model responds is gathered from the mention of those event names in transition command invocations.

defaultTrans [IG | CH]

The state transitions specified by the transition command conceptually form a transition matrix. It is allowed to under-specify the matrix, i.e. the entire cross product of states and events does not have to be supplied in transition command invocations. Any transition that is not specified by a transition command will default to the value given to the defaultTrans command. If there is no defaultTrans command invocation in a state model definition, then the default transition is taken to be CH.

initialState state

When a state machine is created, it can be optionally be placed in any of its states. If no initial state is supplied when the state machine is created, then it will be placed in the state state. If the state model definition does not include an invocation of initialState command then the first defined state is taken as the default initial state.

The following shows an example of a simple two-state state model. Note that state s2 signals an event to itself.

::oomoore model create m1 {
    state s1 {a} {
        chan puts $a
    }
    transition s1 - e1 -> s2
    transition s1 - e2 -> IG
    state s2 {a b} {
        chan puts "$a $b"
        my signal e2 $a
    }
    transition s2 - e2 -> s1
}

STATE MODEL METHODS

The state model class created from the ::oomoore model meta-class supports the following methods.

smclass states

The states method returns a list of the state names for the state model.

smclass events

The states method returns a list of the events names for the state model.

smclass transitions

The transitions method returns a list of triples giving the transitions for the state model. Each list element is in turn a list of three items giving the state name, event name and the name of the destination state of the transition.

smclass initialstate

The initialstate method returns the name of the initial state of the state model.

smclass defaulttransition

The defaulttransition method returns the name of the pseudo-state, either IG or CH, that is the default transition for the state model.

smclass dot

The dot method returns a string which the representation of the directed graph of the state model in the syntax of dot(1) (see graphviz for details of the dot program). The dot(1) command can be used to obtain a pictorial representation of the state model directed graph.

smclass dotfile filename

The dotfile method invokes the dot method and places the result into the file given by, filename.

smclass draw ?dotargs?

The draw method invokes the dot subcommand handing the output to dot(1) to render the state model graph in PostScript. Additional arguments to dot(1) may be present. By default dotargs is set to -Tps -o%s.ps -Gsize=7.5,10 to produce a letter sized, portrait layout of the graph. All occurrences of %s in the dotargs are replaced by the name of the state model.

STATE MACHINE METHODS

State machine objects created from a state model class have the following methods.

smclass create smobj ?initialState?
smclass new ?initialState?

The constructor for objects created from a state model class accept a single, optional argument that is the initial state into which the state machine represented by the object is placed. If initialState is not specified, then the default intial state specified when the state model was created is used.

N.B. that the action associated with the initial state is not executed.

smobj signal event ?param1 param2 ...?

The signal method arranges for event to be delivered to the smobj state machine. The event must be a defined event of the state model from which smobj was created. When the smobj state machine transitions to a new state, the optional paramN parameters are supplied as arguments to the new state. These arguments must match the number of arguments expected by the state action or a run-time error will be generated.

smobj delayedSignal time event ?param1 param2 ...?

The delayedSignal method arranges for the event event to be delivered to the smobj state machine after at least time milliseconds have elapsed. The event must be a defined event of the smobj state machine. The optional paramN parameters are supplied as arguments to the transitioned state. These arguments must match the number of arguments expected by the state action or a run-time error will be generated. Delayed signals enforce the rule that there can be no more than one outstanding delayed signal of a given event between any sending / receiving pair. Thus delayed signals are identified by the source of the signal, the event and the target state machine. If a duplicate delayed signal is requested, then the the previous signal is canceled and a new signal in instanciated at the new delay time.

smobj cancel event

The cancel method cancels the delivery of the delayed signal associated with event. The return value of the method is a boolean indicating whether the signal was indeed canceled. This value may be false in the case where the delayed signal was never generated or if the signal has already expired and been delivered.

smobj remaining event

The remaining method returns the number of milliseconds that must elapse before the delayed signal associated with event will be delivered. The returned value can be zero in the case where the delayed signal was not generated or if the delayed signal has already been delivered.

smobj receive event ?param1 param2 ...?

The receive method performs a synchronous reception of event, transitioning the machine and executing the state action of the new state arranging for the the values given by the optional paramN arguments to be arguments of the state action. This command may be invoked to accomplish the synchronous delivery of event with it parameters and is the same command executed internally when asynchronously delivered events are finally delivered. Typically, events are signaled to a state machine using the signal or delayedSignal methods. These methods insure that the state action completes before the result of the signal delivery takes effect (.i.e. run-to-completion is insured). However, for isolated state machines that do not interact with other state machines, the receive method is convenient and does not require the program to enter the Tcl event loop.

smobj force state ?param1 param2 ...?

The force method forces a transition from the current state to the state given by state and executes the body of code associated with the state. Optional paramN parameters must be given to match the signature of state. This command is sometimes useful for error or reset processing.

smobj currentstate

The currentstate method returns the name of the state in which the state machine currently resides.

smobj loglevel ?level?

The loglevel sets or queries the current logging level for the state machine object. The return value is the current logging level. If the level argument is provided then the logging level is set to level. Log level are those provided by the logger package.

EVENT DISPATCH

The ::oomoore package uses the tcllib uevent package to deliver asychronous events. The uevent package in turn uses the Tcl event loop to generate events. Ultimately, all signaled events are delivered via an ::after command script. This implies that the Tcl event loop must be entered to deliver asynchronous events and errors in the dispatch are reported via the usual background error handling (see ::interp bgerror). For Tk programs, the Tcl event loop is automatically entered. However, for ordinary Tcl scripts, it is necessary to use a command like ::vwait to explicitly enter the Tcl event loop. The example below shows such a usage.

TRANSITION TRACING

The oomoore package uses the tcllib logger package to provide logging facilities. To trace the event dispatch and transition information for a particular state machine it is necessary set the logging level to at least the info level using the loglevel method. Any errors encountered are reported at the error logging level.

EXAMPLE

In this example, a state model called tank_operation is created. The actions are contrived to have the state machines progress through a sequence of states using delayed signals. A simple count variable is used to demonstrate access to object variables.

package require oomoore
# State model
::oomoore model create tank_operation {
    state empty {} {
        my variable count
        chan puts "empty $count"
        incr count
        set ::done 1    ; # used to signal the end of a cycle
    }
    transition empty - pump -> filling
    state filling {} {
        my delayedSignal 500 full   ; # drive my self to the next state
        my variable count
        chan puts "filling $count"
        incr count
    }
    transition filling - full -> full
    state full {} {
        my delayedSignal 500 pump
        my variable count
        chan puts "full $count"
        incr count
    }
    transition full - pump -> emptying
    state emptying {} {
        my delayedSignal 500 empty
        my variable count
        chan puts "emptying $count"
        incr count
    }
    transition emptying - empty -> empty
}
::oo::class create tank {
    # State machine created as a subclass of the state model.
    superclass ::tank_operation
    constructor {} {
        next
        my variable count
        set count 0
    }
}
# Create a state machine object
tank create mytank
# Log the transitions
mytank loglevel info
# Kick things off
mytank signal pump
# Wait for one cycle to complete
vwait ::done

Running the above script yields the following output.

[Wed Jun 05 07:42:32 PDT 2013] [::oomoore::mytank] [info] 'Signal: {} - pump {} -> ::mytank'
[Wed Jun 05 07:42:32 PDT 2013] [::oomoore::mytank] [info]\\ 
    'Transition: ::mytank: empty - pump -> filling'
filling 0
[Wed Jun 05 07:42:33 PDT 2013] [::oomoore::mytank] [info] 'Signal: ::mytank - full {} -> ::mytank'
[Wed Jun 05 07:42:33 PDT 2013] [::oomoore::mytank] [info]\\ 
    'Transition: ::mytank: filling - full -> full'
full 1
[Wed Jun 05 07:42:33 PDT 2013] [::oomoore::mytank] [info] 'Signal: ::mytank - pump {} -> ::mytank'
[Wed Jun 05 07:42:33 PDT 2013] [::oomoore::mytank] [info]\\ 
    'Transition: ::mytank: full - pump -> emptying'
emptying 2
[Wed Jun 05 07:42:34 PDT 2013] [::oomoore::mytank] [info] 'Signal: ::mytank - empty {} -> ::mytank'
[Wed Jun 05 07:42:34 PDT 2013] [::oomoore::mytank] [info]\\ 
    'Transition: ::mytank: emptying - empty -> empty'
empty 3

Keywords

Events, Moore, States, TclOO, Transitions