PIP  0.4.0_beta2
Platform-Independent Primitives
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PIStateMachine< Type > Class Template Reference

Base class for custom state machine. More...

+ Inheritance diagram for PIStateMachine< Type >:

Classes

struct  Rule
 Rule of transition between states of machine More...
 
struct  State
 State of machine More...
 

Public Types

typedef PIPair< PIString, int > Condition
 Condition is a pair (string, number)
 

Public Member Functions

 PIStateMachine (void *_parent=0)
 Constructs an empty state machine.
 
void addState (Type value, const PIString &name="", Handler handler=0)
 Add state of machine.
 
int statesCount () const
 States count.
 
void clearStates ()
 Remove all states.
 
void addRule (Type from, Type to, const PIString &condition, Handler handler=0, bool autoTransition=false, bool resetAllConditions=false)
 Add rule of transition.
 
void addRule (Type from, Type to, Handler handler, bool autoTransition=false, bool resetAllConditions=false)
 Add rule of transition.
 
void addRule (Type from, Type to, const PIStringList &conditions=PIStringList(), Handler handler=0, bool autoTransition=false, bool resetAllConditions=false)
 Add rule of transition.
 
void addRule (const Rule &rule)
 Add rule of transition.
 
int rulesCount () const
 Rules count.
 
void clearRules ()
 Remove all rules.
 
void setInitialState (Type value)
 Setup initial state. reset() will set machine state to "value".
 
bool switchToState (Type to)
 Try to switch machine state to state "to". More...
 
void reset ()
 Reset machine state to initial and clear all conditions.
 
const StatecurrentState () const
 Returns current state of machine.
 
void resetConditions ()
 Reset all performed conditions.
 
void resetCondition (const PIString &name)
 Reset performed condition with name "name".
 
void performCondition (const PIString &name, int times=1)
 Perform condition with name "name" "times" times.
 
void performConditions (const PIStringList &names)
 Perform every condition with name from "names" one time.
 
const PIVector< Condition > & currentConditions () const
 Returns all current performed conditions.
 
- Public Member Functions inherited from PIObject
 PIObject (const PIString &name=PIString())
 Contructs PIObject with name "name".
 
PIString name () const
 Returns object name.
 
virtual const char * className () const
 Returns object class name.
 
bool debug () const
 Return if debug of this object is active.
 
void setName (const PIString &name)
 Set object name.
 
void setDebug (bool debug)
 Set object debug active.
 
const PIMap< PIString,
PIVariant > & 
properties () const
 Returns properties of the object.
 
int propertiesCount () const
 Returns properties count of the object.
 
PIVariant property (const PIString &name) const
 Returns property with name "name".
 
void setProperty (const PIString &name, const PIVariant &value)
 Set property with name "name" to "value". If there is no such property in object it will be added.
 
bool isPropertyExists (const PIString &name) const
 Returns if property with name "name" exists.
 

Protected Member Functions

virtual void execution (const State &state)
 Reimplement this function to process current state of machine.
 
virtual void transition (const State &from, const State &to)
 Reimplement this function to process switching current state of machine.
 
- Protected Member Functions inherited from PIObject
PIObjectemitter () const
 Returns PIObject* which has raised an event. This value is correct only in definition of some event handler.
 
virtual void propertyChanged (const PIString &name)
 Virtual function executes after property with name "name" has been changed.
 

Handlers

void tick ()
 Main function of machine. Execute execution() and check if need to switch state.
 
void tick (void *data, int delim)
 Main function of machine. Execute execution() and check if need to switch state.
 

Additional Inherited Members

- Static Public Member Functions inherited from PIObject
static void piDisconnect (PIObject *src, const PIString &sig)
 Disconnect object "src" from all connections with event name "sig".
 
static void piDisconnect (PIObject *src)
 Disconnect object "src" from all connections, i.e. all connections where object "src" is emitter.
 
static PIObjectfindByName (const PIString &name)
 Returns PIObject* with name "name" or 0, if there is no object found.
 

Detailed Description

template<typename Type = int>
class PIStateMachine< Type >

Base class for custom state machine.

Synopsis

This class provide functionality of state machine. You should inherit from this class, implement execution() and transition() functions, set rules and periodically call tick() function to proper work of machine.

Prepare for work

State machine operates with "state", "rule" and "condition".

  • "State" is some class (by default int), associated name and optional "handler" - pointer to function executed on every tick();
  • "Rule" define rule of transition from one machine state to other. It is also has optional "handler";
  • "Condition" is a part of rule and define possibility of transition.

First of all you should define states of your machine by function addState(). Then you should define transition rules for machine by function addRule(). Finally you can set initial state by function setInitialState() and provide periodically execution of function tick().

Principle of work

At any time the state machine is in some state. You can ask machine to enter in new state by function switchToState(). If all conditions done machine switch it state immediately, else machine remember request and will be try switch to the new state every tick. Successfull state switching execute function transition(), every tick execute function execution() with current state. On successfull transition if rule "handler" is not null it execute. Every tick() if current state "handler" is not null it execute.

Conditions

Each rule has transition condition. Condition is array of pairs (string, number). It means that every condition by name "string" should be performed as least "number" times. Empty condition always permits transition.

State machine have current performed conditions. You can read this conditions by function currentConditions() and perform new conditions by functions performCondition() and performConditions(). Currend conditions can de erased by function resetConditions().

Example

This is simple example demonstrates all features:

#include "pip.h"
enum Mode {Start, Manual, Auto, Finish, End};
class Machine: public PIStateMachine<Mode> {
PIOBJECT(Machine)
public:
Machine() {
addState(Start, "start", HANDLER(startFunc));
addState(Manual, "manual", HANDLER(manualFunc));
addState(Auto, "auto", HANDLER(autoFunc));
addState(Finish, "finish", HANDLER(finishFunc));
addState(End, "end", HANDLER(endFunc));
addRule(Start, Manual, "init_ok", HANDLER(beginManualFunc));
addRule(Start, Auto, "init_ok", HANDLER(beginAutoFunc));
addRule(Manual, Auto, HANDLER(manualToAutoFunc));
addRule(Auto, Manual, HANDLER(autoToManualFunc));
addRule(Manual, Finish);
addRule(Auto, Finish);
Rule r(Finish, End);
r.addCondition("finish_0_ok");
r.addCondition("finish_1_ok", 2);
addRule(r);
CONNECT2(void, void*, int, &timer, timeout, this, tick);
timer.start(500);
}
virtual void execution(const State & state) {
piCout << "performed conditions:" << currentConditions();
}
virtual void transition(const State & from, const State & to) {
piCout << "switch from" << from.name << "to" << to.name << "state";
}
EVENT_HANDLER(void, startFunc) {piCout << "start function";}
EVENT_HANDLER(void, manualFunc) {piCout << "manual function";}
EVENT_HANDLER(void, autoFunc) {piCout << "auto function";}
EVENT_HANDLER(void, finishFunc) {piCout << "finish function";}
EVENT_HANDLER(void, endFunc) {piCout << "end function";}
EVENT_HANDLER(void, beginManualFunc) {piCout << "begin manual function";}
EVENT_HANDLER(void, beginAutoFunc) {piCout << "begin auto function";}
EVENT_HANDLER(void, autoToManualFunc) {piCout << "switch from auto to manual function";}
EVENT_HANDLER(void, manualToAutoFunc) {piCout << "switch from manual to auto function";}
PITimer timer;
};
Machine machine;
void key_event(char key, void*) {
switch (key) {
case 's': machine.switchToState(Start); break;
case 'm': machine.switchToState(Manual); break;
case 'a': machine.switchToState(Auto); break;
case 'f': machine.switchToState(Finish); break;
case 'e': machine.switchToState(End); break;
case '1': machine.performCondition("init_ok"); break;
case '2': machine.performCondition("finish_0_ok"); break;
case '3': machine.performCondition("finish_1_ok"); break;
case 'r': machine.resetConditions(); break;
case 'R': machine.reset(); break;
}
}
int main(int argc, char * argv[]) {
PIKbdListener kbd(key_event);
kbd.enableExitCapture();
WAIT_FOR_EXIT
};

Member Function Documentation

template<typename Type = int>
bool PIStateMachine< Type >::switchToState ( Type  to)
inline

Try to switch machine state to state "to".

If there is rule of transition exists and this rule conditions is performed then machine switched to new state immediately. Otherwise machine will be try to enter to new state every tick().

Returns
true if state switched immediately, otherwise false