sttcl  v0.9c
STTCL C++ template state machine framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Usage of the STTCL state machine template class framework

2 Usage of the STTCL state machine template class framework

2.1 Declare a StateMachine implementation
2.2 Declare State implementations
2.3 Implement the state machine interfaces
2.4 STTCL 'implementation hooks'
2.5 Implement state actions and transitions
2.6 Composite states
2.7 Composite state regions, forks/joins

2.1 Declare a StateMachine implementation

Analyze your UML 2.2 state diagram and declare all necessary variables and event (trigger methods) needed for the state machine. Declare an appropriate instance of sttcl::StateMachine as base class for your state machine class.

class MyStateMachine;
class IStateEventHandlers
{
public:
virtual handleEvent1(MyStateMachine* context) = 0;
virtual handleEvent2(MyStateMachine* context) = 0;
};
class MyStateMachine : public sttcl::StateMachine<MyStateMachine,IStateEventHandlers>
{
public:
void event1();
void event2();
int getX() const;
const std::string& getY();
// ...
};

According to the GoF state pattern implementation variants you can decide where to hold the necessary state instances and make their sibling states accessible for them, so they can realize event triggered transitions. As a rule of thumb the state implementation classes can be instantiated as singletons (see GoF Singleton pattern) if they have no member variables other than application scope configurations. Otherwise the available states should be embedded members of the state machine implementation class and are accessible from the state machine context for state implementation classes.

Note:
State implementation classes inheriting from the sttcl::ActiveState or sttcl::CompositeState template classes implicitly have embedded members in the base classes.

2.2 Declare State implementations

Implement a state class for each state in your UML 2.2 state machine diagram. Declare the appropriate instance of the sttcl::State template class as base class for all state classes.

class MyStateMachine;
class MyState1 : public sttcl::State<MyState1,MyStateMachine,IStateEventHandlers>
{
// ...
};

2.3 Implement state machine interface

The event1() and event2() method implementations of MyStateMachine can just delegate to the matching call to the IStateEventHandlers interface of the current state

void MyStateMachine::event1()
{
IStateEventHandlers* currentState = getState();
if(currentState)
{
currentState->handleEvent1(this);
}
}

2.4 STTCL 'implementation hooks'

The STTCL template base classes provide so called 'implementation hooks' to enable an implementation class to override certain methods of the base class implementation. As soon the implementation class provides an implementation hook method it will be called without using the vtable. The implementing class should always call the base classes implementation of the implementation hook method to ensure the correct behavior of the state machine, unless you want to reimplement the basic behavior yourself.

void MyState::entryImpl(MyStateMachine* context)
{
// Provide state specific entry actions
// ...
// Call the base class implementation
State<MyState,MyStateMachine,IState>::entryImpl(context);
}

2.5 Implement state actions and transitions

Transition actions are implemented within the event handler methods of the state classes. See the table in 3 Mapping of the UML state diagram notation elements to the GoF State pattern for more details how UML2.2 state diagram elements can be implemented using the GoF state pattern and STTCL.

State entry and exit actions can be implemented using the implementation hooks entryImpl() and exitImpl() in the state implementation class.

State do actions can be implemented in a method of the state implementation class, that is passed to the base class constructor. The sttcl::ActiveState base class supports asynchronous execution of the state do action. It implements a thread function loop, that calls the do action method until the state is exited.

Direct state transitions (i.e. transitions between states without a triggering event method) are a special case. You can handle these by overriding the checkDirectTransitionImpl() implementation hook in the state implementation class.

2.6 Composite states

To implement composite states you can use the sttcl::CompositeState template base class. This class inherits both, the sttcl::State and the sttcl::StateMachine template base classes. The first is used to specify a valid state signature to embed the composite state implementation in an outer state machine implementation. The second specifies the sub state machine of the composite state and specifies the signature for any inner states of the composite state implementation.

To use a history pseudo state within the composite state diagram you may optionally specify the HistoryType template parameter. The state history behavior will automatically appear on any entry of the composite state implementation until it is (re-)initialized.

2.7 Composite state regions, forks/joins

If you need orthogonal state machine regions or transition paths that go out a fork pseudo state you can use the sttcl::ConcurrentCompositeState and sttcl::Region template base classes. The sttcl::ConcurrentCompositeState base class needs to be initialized with a fixed array of pointers to sttcl::Region implementation instances in the constructor. The overall number of regions contained in the sttcl::ConcurrentCompositeState implementation is specified using the NumOfRegions template parameter. To broadcast events to the contained regions the state interface methods used for the sttcl::ConcurrentCompositeState implementation need to have a special signature as follows:

typedef void (StateInterface::*OuterEventHandler)(StateMachineImpl*);

Each of the sttcl::Region implementations runs its own internal thread, where state transitions of the contained states (including initialization, finalization and history behavior) are performed. That event method calls to the sttcl::ConcurrentCompositeState IInnerState interface methods can be dispatched to these region threads, all of the inner state interfaces methods need to have a special signature as follows:

typedef void (InnerState::*InnerEventHandler)(StateMachineImpl*,RegionBase<StateMachineImpl,StateInterface,IInnerState>*);

You can also specify a type or class to pass additional event arguments to the dispatched event methods. These event arguments need to be managed using a thread safe smart pointer that is provided with the sttcl::RefCountPtr template class. If you specify the EventArgs template parameter to the sttcl::ConcurrentCompositeState and matching sttcl::Region classes, the outer and inner state interface method signatures must look like this:

typedef void (StateInterface::*OuterEventHandler)(StateMachineImpl*,RefCountPtr<EventArgs>);
typedef void (InnerState::*InnerEventHandler)(StateMachineImpl*,RegionBase<StateMachineImpl,StateInterface,IInnerState>*,RefCountPtr<EventArgs>);

Its your responsibility to create an appropriate hierarchy of event argument classes and to decode these for particular event methods if necessary. The RefCountPtr template needs to be instantiated with a common base class in this case.

Fork pseudo states can be represented by a sttcl::ConcurrentCompositeState implementation providing a region for each of the forks outgoing transitions. A join pseudo state equivalents the finalized state of the sttcl::ConcurrentCompositeState class.