This library is designed to create and run state graphs. It supports hierarchical states and parallel states execution.

StateMachineLib/StateMachine.h

Committer:
martin13
Date:
2019-02-12
Revision:
3:d4d69d0d8381
Parent:
0:f4fdca2c4c67

File content as of revision 3:d4d69d0d8381:

////////////////////////////////////////////////////////////////////////////////
// Copyright Rottor SAS 2017
// All rigths reserved.
//
// File Name : StateMachine.h
// Authors : Martin Matignon
//
// If you find any bug or if you have any question please contact
// Martin Matignon <martin.matignon@rottor.fr>
// Nicolas Forestier <nicolas.forestier@rottor.fr>
//
////////////////////////////////////////////////////////////////////////////////

#ifndef __SM_STATE_MACHINE_H__
#define __SM_STATE_MACHINE_H__

#include <string>
#include "Transitions.h"

// Macro to cast derived State pointer object
#define STATE(S) ((State*)S)

typedef const char* OUTCOME;


/** A class to store and map the states graph and execute
 */
class StateMachine : public State{
  
public:

    /** Structure to store list of(state/transitions) :
     *  { state : transition{ outcome: target, ...}, ... }
     */
    typedef struct StateItem_t{
        
        State       *state;
        Transitions *transitions;
        StateItem_t *next;
        
        StateItem_t(State* _state);
        
    } StateItem_t;
    
    /** Create a StateMachine
     * 
     *  @param const char* The state machine uuid
     *  @param UserData*   The user data object pointer
     */
    StateMachine(const char* stateMachineUUID, UserData *ud = new UserData());
    
    /** Set the initial state to execute
     *
     *  @param State* The initial state
     */
    void setInitialState(State* state);
    
    
    /** Instance state with state machine context
     *
     * @param const char* The state uuid
     */
    template<typename T>
    inline T* Instance(const char* uuid){
        
        // State instance with user data context
        T* state = new T(uuid, m_userData);
        
        // Registe state into state machine
        this->_addState(STATE(state));
        
        // Routing preempt outcome
        this->connect(STATE(state), PREEMPTED, PREEMPTED);
        
        return state;
    }
    
    /** Method for routing state outcome to other state
     * (Connect state outcome to state target)
     *
     * @param State*      The pointer state object
     * @param const char* The state outcome
     * @param State*      The pointer target state
     */
    void connect(State* state, const char* outcome, State* target);
    
    /** Remap state outcome to other state
     *
     * @param State*      The pointer state object
     * @param const char* The state outcome
     * @param State*      The pointer target state
     */
    void remap(State* state, const char* outcome, State* target);
    
    /** Method for routing state outcome to exit outcome
     *
     * @param State*      The pointer state object
     * @param const char* The state outcome
     * @param const char* The exit outcome
     */
    void connect(State* state, const char* outcome, const char* _exit);
    
    /** Remap state outcome to exit outcome
     *
     * @param State*      The pointer state object
     * @param const char* The state outcome
     * @param const char* The exit outcome
     */
    void remap(State* state, const char* outcome, const char* _exit);
    
    /** Before state machine execution (Empty)
     * (You can redefine this method in inherited object)
     */
    virtual void onEntry();
    

    /** State machine execution (Execute graph state)
     *
     * @return const char* The state machine outcome
     */
    virtual const char* onExecute();
    
    
    /** After state machine execution (Empty)
     * (You can redefine this method in inherited object)
     */
    virtual void onExit();
    
    /** The ROOT state machine execution
     *
     * @return const char* The root state machine outcome
     */
    const char* execute();
    
    /** Provide the states list registered into state machine
     *
     * @return StateItem_t* The pointer states list
     */
    StateItem_t* getStatesList();
    
    /** Provide the number of states registered into state machine
     *
     * @return int The number of state into state machine
     */
    int getNumberStates();
    
    /** Provide the user data object
     *
     * @return UserData* The pointer user data object
     */
    UserData* getUserData();
    
    /** Print the graph states
     */
    void printGraph(string level="");
    
private:

    /** Adding a new state
     *
     *  @param State* The state object
     */
    void _addState(State *state);
    
    
    /** Provide the item list by uuid
     *
     * @return StateItem_t* The item structure
     */
    StateItem_t* getItemByUUID(const char* uuid);

    StateItem_t   *m_stateList;
    int            m_nbStates;
    StateItem_t   *m_currentItem;
    const char    *m_initalStateUUID;
    const char    *m_targetStateUUID;
    UserData      *m_userData;
};

#endif /* #ifndef __SM_STATE_MACHINE_H__*/