7
\$\begingroup\$

Preface

I have decided to let my pet project created some years ago to undergo a code review here.

The review will be broken into parts according to meta question Multiple reviews or one big review?.

The overall concept and motivation can be inspected here (be patient, it takes some time to load).

The doxygen generated documentation can be accessed online here (it loads a bit quicker).


The basic idea

The GoF design pattern catalogue proposes the State Pattern which can merely boiled down that the State provides a specific interface that is delegate called by the StateMachine's public functions to a current concrete State implementation.

Now according to the UML notation there are specific standardized methods that apply for a State like enter(), exit() or do(). The other internal interface methods are context and application specific, and have to be implemented for a concrete implementation.

The goal of STTCL is to make it easier to create StateMachine implementations translating from UML StateMachine diagrams. Something like this:

enter image description here

                                           |     |
                                           |     |
                                           |     |
                                          \       /
                                           \     /
                                            \   /
                                             \ /
                                              V

enter image description here

Any kind of critique and annotation is appreciated. All the test cases and demos are running fine and as intended BTW.

Part I: Core classes and basic interfaces

enter image description here

StateMachine.h

/* license header omitted */
#ifndef STATEMACHINE_H_
#define STATEMACHINE_H_

#include "SttclConfig.h"

#include "State.h"
#include <cassert>
#if defined(STTCL_DEBUG)
#include <iostream>
#if defined(STTCL_HAVE_RTTI)
#include <typeinfo>
#endif
#endif

#if defined(STTCL_USE_STL)
#include <set>
#endif

#if defined(STTCL_THREADSAFE_IMPL)
#include "SttclMutex.h"
#endif

namespace sttcl
{

/**
 * State machine flags bitfield.
 */
struct StateMachineFlags
{
    /**
     * Indicates that the state machine is initialized.
     */
    unsigned char initialized:1;
    /**
     * Indicates that the state machine is currently initializing.
     */
    unsigned char initializing:1;
    /**
     * Indicates that the state machine is finalized.
     */
    unsigned char finalized:1;
    /**
     * Indicates that the state machine is currently finalizing.
     */
    unsigned char finalizing:1;


    inline StateMachineFlags(const StateMachineFlags& rhs)
    : initialized(rhs.initialized)
    , initializing(rhs.initializing)
    , finalized(rhs.finalized)
    , finalizing(rhs.finalizing)
    {
    }

    inline StateMachineFlags& operator=(const StateMachineFlags& rhs)
    {
        initialized = rhs.initialized;
        initializing= rhs.initializing;
        finalized = rhs.finalized;
        finalizing = rhs.finalizing;
        return *this;
    }

    static const StateMachineFlags& Initializing()
    {
        static StateMachineFlags initializingFlags(false,true,false,false);
        return initializingFlags;
    }

    static const StateMachineFlags& Initialized()
    {
        static StateMachineFlags initializedFlags(true,false,false,false);
        return initializedFlags;
    }

    static const StateMachineFlags& Finalizing()
    {
        static StateMachineFlags finalizingFlags(false,false,false,true);
        return finalizingFlags;
    }

    static const StateMachineFlags& Finalized()
    {
        static StateMachineFlags finalizedFlags(false,false,true,false);
        return finalizedFlags;
    }

    static const StateMachineFlags& Empty()
    {
        static StateMachineFlags emptyFlags;
        return emptyFlags;
    }

protected:
    /**
     * Constructor for StateMachineFlags.
     */
    inline StateMachineFlags()
    : initialized(false)
    , initializing(false)
    , finalized(false)
    , finalizing(false)
    {
    }

    inline StateMachineFlags(bool initialized_, bool initializing_, bool finalized_, bool finalizing_)
    : initialized(initialized_)
    , initializing(initializing_)
    , finalized(finalized_)
    , finalizing(finalizing_)
    {
    }

};

/**
 * Represents the base class for a state machine.
 *
 * @tparam StateMachineImpl Specifies the class implementing the state machine.
 * @tparam IState Specifies the internal interface of state implementations for the state
 *                machine.
 */
template
    < class StateMachineImpl
    , class IState
#if defined(STTCL_THREADSAFE_IMPL)
    , class StateMachineMutexType = sttcl::internal::SttclMutex<STTCL_DEFAULT_MUTEXIMPL>
#endif
    >
class StateMachine
{

public:
#if defined(STTCL_THREADSAFE_IMPL)
    typedef StateMachineMutexType MutexType;
#endif
    /**
     * The state machine implementation type.
     */
    typedef StateMachineImpl Context;
    /**
     * The internal state implementation interface.
     */
    typedef IState StateInterface;
    /**
     * The internal state implementation base type.
     */
    typedef StateBase<StateMachineImpl,IState> StateBaseClass;

    friend class StateBase<StateMachineImpl,IState>;

    /**
     * Destructor for class StateMachine.
     */
    ~StateMachine()
    {
        if(isInitialized() && !isFinalizing() && !isFinalized() && getState())
        {
            finalize();
        }
    }

    /**
     * Initializes the state machine.
     * @param force Indicates to finalize the state machine before (re-)initializing.
     * @return The ready state of the state machine.
     */
    bool initialize(bool force = false)
    {
        bool result = false;
        if(force || (!isInitialized() && !isInitializing()) )
        {
            setStateMachineFlags(StateMachineFlags::Initializing());
            result = static_cast<Context*>(this)->initializeImpl(force);
        }
        if(result)
        {
            setStateMachineFlags(StateMachineFlags::Initialized());
            result = isReady();
        }
        else
        {
            setStateMachineFlags(StateMachineFlags::Empty());
        }
        return result;
    }

    /**
     * Finalizes the state machine.
     *
     * @param finalizeSubStateMachines Indicates to finalize any sub state machines.
     */
    void finalize(bool finalizeSubStateMachines = true)
    {
        if(!isFinalized() && !isFinalizing())
        {
            setStateMachineFlags(StateMachineFlags::Finalizing());
            static_cast<Context*>(this)->finalizeImpl(finalizeSubStateMachines);
            setStateMachineFlags(StateMachineFlags::Finalized());
        }
    }

    /**
     * Indicates that the state machine is ready to process events.
     * @return \c true if the state machine is ready to process events, \c false otherwise.
     */
    inline bool isReady() const
    {
        return static_cast<const Context*>(this)->isReadyImpl();
    }

    /**
     * Default implementation for isReady().

     * @return \c true if the state machine is ready to process events, \c false otherwise.
     */
    inline bool isReadyImpl() const
    {
        STTCL_STATEMACHINE_SAFE_RETURN(internalLockGuard,flags.initialized && !flags.finalized);
    }

    /**
     * Indicates that the state machine is initialized.
     * @return \c true if the state machine is initialized, \c false otherwise.
     */
    bool isInitialized() const
    {
        STTCL_STATEMACHINE_SAFE_RETURN(internalLockGuard,(flags.initialized && !flags.initializing && !flags.finalizing && !flags.finalized));
    }

    /**
     * Sets the initialized flag of the state machine.
     */
//    void setInitialized(bool value)
//    {
//        STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
//        flags.initialized = value;
//        STTCL_STATEMACHINE_SAFESECTION_END;
//    }

    /**
     * Indicates that the state machine is currently initializing.
     * @return \c true if the state machine is currently initializing, \c false otherwise.
     */
    bool isInitializing() const
    {
        STTCL_STATEMACHINE_SAFE_RETURN(internalLockGuard,flags.initializing);
    }

    void setStateMachineFlags(const StateMachineFlags& value)
    {
        STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
        flags = value;
        STTCL_STATEMACHINE_SAFESECTION_END;
    }

    /**
     * Sets the initializing flag of the state machine.
     */
//    void setInitializing(bool value)
//    {
//        STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
//        flags.initializing = value;
//        STTCL_STATEMACHINE_SAFESECTION_END;
//    }

    /**
     * Indicates that the state machine is finalized.
     * @return \c true if the state machine is finalized, \c false otherwise.
     */
    bool isFinalized() const
    {
        STTCL_STATEMACHINE_SAFE_RETURN(internalLockGuard,(flags.finalized && !flags.initializing && !flags.initialized));
    }

    /**
     * Sets the finalized flag of the state machine.
     */
//    void setFinalized(bool value)
//    {
//        STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
//        flags.finalized = value;
//        STTCL_STATEMACHINE_SAFESECTION_END;
//    }

    /**
     * Indicates that the state machine is currently finalizing.
     * @return \c true if the state machine is currently finalizing, \c false otherwise.
     */
    bool isFinalizing() const
    {
        STTCL_STATEMACHINE_SAFE_RETURN(internalLockGuard,flags.finalizing);
    }

    /**
     * Sets the finalizing flag of the state machine.
     */
    void setFinalizing(bool value)
    {
        STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
        flags.finalizing = value;
        STTCL_STATEMACHINE_SAFESECTION_END;
    }

    /**
     * Gets the current state.
     *
     * @return The current state.
     */
    inline StateBaseClass* getState() const
    {
        STTCL_STATEMACHINE_SAFE_RETURN(internalLockGuard,state);
    }

    /**
     * Default implementation for the initialize() method.
     * @param force Indicates to finalize the state machine before (re-)initializing.
     * @return The ready state of the state machine.
     */
    inline bool initializeImpl(bool force)
    {
        if(force)
        {
            StateBaseClass* currentState = getState();
            if(currentState)
            {
                currentState->finalizeSubStateMachines(true);
            }
            if(!isFinalized())
            {
                finalize(true);
            }
        }

        StateBaseClass* initialState = getInitialState();
        if(initialState)
        {
            changeState(initialState);
        }
        StateBaseClass* currentState = getState();
        if(currentState)
        {
            currentState->initSubStateMachines(force);
        }

        return true;
    }

    /**
     * Default implementation for the finalize() method.
     *
     * @param finalizeSubStateMachines Indicates to finalize any sub state machines.
     */
    inline void finalizeImpl(bool finalizeSubStateMachines)
    {
        if(state)
        {
            if(finalizeSubStateMachines)
            {
                state->finalizeSubStateMachines(true);
            }
            exitCurrentState();
        }
        setState(0);
        pickUpRunningActiveStates();
    }

    /**
     * Called by a contained (composite) state when its sub state machine is completed (finalized).
     * @param state A pointer to the contained (composite) state.
     */
    inline void subStateMachineCompleted(StateBaseClass* state)
    {
        static_cast<StateMachineImpl*>(this)->subStateMachineCompletedImpl(state);
    }

    /**
     * The default implementation of the subStateMachineCompleted method.
     * @param state A pointer to the contained (composite) state.
     */
    inline void subStateMachineCompletedImpl(StateBaseClass* state)
    {
    }

    inline void registerActiveStateRunning(StateBaseClass* state)
    {
        STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
            if(activeStatesRunning.find(state) == activeStatesRunning.end())
            {
                activeStatesRunning.insert(state);
            }
        STTCL_STATEMACHINE_SAFESECTION_END;
    }

    inline void unregisterActiveStateRunning(StateBaseClass* state)
    {
        STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
            if(activeStatesRunning.find(state) != activeStatesRunning.end())
            {
                activeStatesRunning.erase(state);
            }
        STTCL_STATEMACHINE_SAFESECTION_END;
    }

    /**
     * Default implementation to set the state machine to \c isReady() conditions.
     */
    virtual void setReady()
    {
        static_cast<StateMachineImpl*>(this)->setReadyImpl();
    }

    /**
     * Default implementation to set the state machine to \c isReady() conditions.
     */
    inline void setReadyImpl()
    {
        STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
            flags.finalized = false;
            flags.initialized = true;
        STTCL_STATEMACHINE_SAFESECTION_END;
    }

    /**
     * Gets the initial state of the state machine.
     *
     * @return The initial state of the state machine.
     */
    StateBaseClass* getInitialState() const
    {
        StateBaseClass* result = static_cast<const Context*>(this)->getInitialStateImpl();
#if defined(STTCL_DEBUG) // && defined(STTCL_HAVE_RTTI)
        if(!result)
        {
            std::cerr << "WARNING: " << typeid(static_cast<const Context*>(this)).name() << ".getInitialStateImpl() returned NULL" << std::endl;
        }
#endif
        return result;
    }

protected:
    /**
     * Constructor for class StateMachine.
     */
    StateMachine()
    : state(0)
    , flags(StateMachineFlags::Empty())
    {
    }

    /**
     * Changes the state machines current state.
     *
     * @param newState The new target state.
     */
#if defined(STTCL_THREADSAFE_IMPL)
    void changeState(typename StateMachine<StateMachineImpl,IState,StateMachineMutexType>::StateBaseClass* newState);
#else
    void changeState(typename StateMachine<StateMachineImpl,IState>::StateBaseClass* newState);
#endif

    /**
     * Sets the state machines current state without calling any state operations.
     * @param newState
     */
    inline void setState(StateBaseClass* newState)
    {
        STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
            state = newState;
        STTCL_STATEMACHINE_SAFESECTION_END;
    }

    // Default implementations
    //---------------------------------------------------------------------------------------

    /**
     * Default implementation for getInitialState().
     *
     * @return The initial state of the state machine.
     */
    inline StateBaseClass* getInitialStateImpl() const
    {
        return 0;
    }

    void exitCurrentState();
    void enterNewState();

    void pickUpRunningActiveStates();

protected:
    StateBaseClass* state;

private:
    StateMachineFlags flags;
#if defined(STTCL_USE_STL)
    std::set<StateBaseClass*> activeStatesRunning;
#endif
#if defined(STTCL_THREADSAFE_IMPL)
    mutable StateMachineMutexType internalLockGuard;
#endif

};

#if defined(STTCL_THREADSAFE_IMPL)
template<class StateMachineImpl, class IState, class StateMachineMutexType>
void StateMachine<StateMachineImpl,IState,StateMachineMutexType>::changeState(typename StateMachine<StateMachineImpl,IState,StateMachineMutexType>::StateBaseClass* newState)
#else
template<class StateMachineImpl, class IState>
void StateMachine<StateMachineImpl,IState>::changeState(typename StateMachine<StateMachineImpl,IState>::StateBaseClass* newState)
#endif
{
    if(!isFinalizing())
    {
        if(newState)
        {
            if(newState != state)
            {
                exitCurrentState();
                setState(newState);
                enterNewState();
            }
        }
        else // equivalent to finalize
        {
            finalize();
        }
    }
}

#if defined(STTCL_THREADSAFE_IMPL)
template
    < class StateMachineImpl
    , class IState
    , class StateMachineMutexType
    >
void StateMachine<StateMachineImpl,IState,StateMachineMutexType>::exitCurrentState()
{
    if(state)
    {
        state->endDo(static_cast<StateMachine<StateMachineImpl,IState,StateMachineMutexType>::Context*>(this));
        state->exit(static_cast<StateMachine<StateMachineImpl,IState,StateMachineMutexType>::Context*>(this));
    }
}
#else
template
    < class StateMachineImpl
    , class IState
    >
void StateMachine<StateMachineImpl,IState>::exitCurrentState()
{
    if(state)
    {
        state->endDo(static_cast<StateMachine<StateMachineImpl,IState>::Context*>(this));
        state->exit(static_cast<StateMachine<StateMachineImpl,IState>::Context*>(this));
    }
}
#endif

#if defined(STTCL_THREADSAFE_IMPL)
template
    < class StateMachineImpl
    , class IState
    , class StateMachineMutexType
    >
void StateMachine<StateMachineImpl,IState,StateMachineMutexType>::enterNewState()
{
    state->entry(static_cast<StateMachine<StateMachineImpl,IState,StateMachineMutexType>::Context*>(this));
    state->startDo(static_cast<StateMachine<StateMachineImpl,IState,StateMachineMutexType>::Context*>(this));
}
#else
template
    < class StateMachineImpl
    , class IState
    >
void StateMachine<StateMachineImpl,IState>::enterNewState()
{
    state->entry(static_cast<StateMachine<StateMachineImpl,IState>::Context*>(this));
    state->startDo(static_cast<StateMachine<StateMachineImpl,IState>::Context*>(this));
}
#endif

#if defined(STTCL_THREADSAFE_IMPL)
template
    < class StateMachineImpl
    , class IState
    , class StateMachineMutexType
    >
void StateMachine<StateMachineImpl,IState,StateMachineMutexType>::pickUpRunningActiveStates()
#else
template
    < class StateMachineImpl
    , class IState
    >
void StateMachine<StateMachineImpl,IState>::pickUpRunningActiveStates()
#endif
{
    bool allRunningActiveStatesJoined = false;
    do
    {
        STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
            allRunningActiveStatesJoined = activeStatesRunning.empty();
        STTCL_STATEMACHINE_SAFESECTION_END;
        if(!allRunningActiveStatesJoined)
        {
            StateBaseClass* activeStateToJoin = NULL;
            STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard);
                if(!activeStatesRunning.empty())
                {
                    activeStateToJoin = *(activeStatesRunning.begin());
                }
            STTCL_STATEMACHINE_SAFESECTION_END;
            if(activeStateToJoin)
            {
                activeStateToJoin->joinDoAction(static_cast<Context*>(this));
            }
        }
    } while(!allRunningActiveStatesJoined);
}

}

#endif /* STATEMACHINE_H_ */

State.h

/* license header omitted */
#ifndef STATE_H_
#define STATE_H_

#include <SttclConfig.h>

namespace sttcl
{

template
    < class StateMachineImpl
    , class IState
#if defined(STTCL_THREADSAFE_IMPL)
    , class StateMachineMutexType
#endif
    >
class StateMachine;

/**
 * Represents a particular state machines state base class.
 *
 * @tparam StateMachineImpl The state machine implementation type.
 * @tparam IState Specifies the internal interface of state implementations for the state
 *                machine.
 */
template<class StateMachineImpl,class IState>
class StateBase
: public IState
{
#if defined(STTCL_THREADSAFE_IMPL)
    friend class StateMachine<StateMachineImpl,IState,typename StateMachineImpl::MutexType>;
#else
    friend class StateMachine<StateMachineImpl,IState>;
#endif

public:
    /**
     * The state machine implementation type.
     */
    typedef StateMachineImpl Context;

    /**
     * The internal state implementation interface.
     */
    typedef IState StateInterface;

    /**
     * Called by the containing StateMachine to finalize any sub state machines.
     * @param recursive If \c true further sub state machines should be finalized
     *                  recursively.
     */
    virtual void finalizeSubStateMachines(bool recursive) = 0;

    /**
     * Called by the containing StateMachine to initialize any sub state machines.
     * @param recursive If \c true further sub state machines should be initialized
     *                  recursively.
     */
    virtual void initSubStateMachines(bool recursive) = 0;

    /**
     * Called by the containing state machine when the state is entered.
     * @param context A pointer to the containing state machine.
     */
    virtual void entry(Context* context) = 0;
    /**
     * Called by the containing state machine when the state is left.
     * @param context A pointer to the containing state machine.
     */
    virtual void exit(Context* context) = 0;
    /**
     * Called by the containing state machine after the state was entered.
     * @param context A pointer to the containing state machine.
     */
    virtual void startDo(Context* context) = 0;
    /**
     * Called by the containing state machine before the state is left.
     * @param context A pointer to the containing state machine.
     */
    virtual void endDo(Context* context) = 0;

    /**
     * Called by the containig state machine to pickup finished asynchronous doAction threads.
     * @param context A pointer to the containing state machine.
     */
    virtual void joinDoAction(Context* context) = 0;

    /**
     * Default implementation for the changeState() method.
     * @param context A pointer to the containing state machine.
     * @param newState The new sibling state the containing state machine should change to.
     */
    void changeStateImpl(Context* context,StateBase<StateMachineImpl,IState>* newState)
    {
        context->changeState(newState);
    }

    /**
     * Default implementation for the changeState() method.
     * @param context A pointer to the containing state machine.
     * @param newState The new sibling state the containing state machine should change to.
     */
    template<class StateMachineContext>
    void changeStateImpl(StateMachineContext* context,StateBase<StateMachineImpl,IState>* newState)
    {
        context->changeState(newState);
    }
protected:

    /**
     * Constructor for class StateBase.
     */
    StateBase() {}
    /**
     * Destructor for class StateBase.
     */
    virtual ~StateBase() {}

};

/**
 * Represents a particular state machines state implementation base class.
 *
 * @tparam StateImpl The state implementation type.
 * @tparam StateMachine The state machine implementation type.
 * @tparam IState Specifies the internal interface of state implementations for the state
 *                machine.
 */
template<class StateImpl,class StateMachineImpl,class IState>
class State
: public StateBase<StateMachineImpl,IState>
{
public:
    /**
     * The state machine implementation type.
     */
    typedef StateMachineImpl Context;

    /**
     * The implementation class type.
     */
    typedef StateImpl Implementation;

    /**
     * The state base class type.
     */
    typedef StateBase<StateMachineImpl,IState> StateBaseType;

    /**
     * The state do action type.
     * The first parameter is a pointer to the containing state machine, the second parameter
     * indicates that the state do action is called the first time when \c true.
     */
    typedef void (Implementation::*StateDoAction)(Context*,bool);

    /**
     * Default implementation for the entry() method.
     * @param context A pointer to the containing state machine.
     */
    inline void entryImpl(Context* context)
    {
    }

    /**
     * Default implementation for the exit() method.
     * @param context A pointer to the containing state machine.
     */
    inline void exitImpl(Context* context)
    {
    }

    /**
     * Default implementation for the startDo() method.
     * @param context A pointer to the containing state machine.
     */
    inline void startDoImpl(Context* context)
    {
        if(doAction)
        {
            (static_cast<Implementation*>(this)->*doAction)(context,true);
        }
    }

    /**
     * Default implementation for the endDo() method.
     * @param context A pointer to the containing state machine.
     */
    inline void endDoImpl(Context* context)
    {
    }

    /**
     * Default implementation for the joinDoAction() method.
     * @param context A pointer to the containing state machine.
     */
    inline void joinDoActionImpl(Context* context)
    {
    }

    /**
     * Default implementation for the finalizeSubStateMachines() method.
     * @param recursive If \c true further sub state machines should be finalized
     *                  recursively.
     */
    void finalizeSubStateMachinesImpl(bool recursive)
    {
    }

    /**
     * Default implementation for the initSubStateMachines() method.
     * @param recursive If \c true further sub state machines should be initialized
     *                  recursively.
     */
    void initSubStateMachinesImpl(bool recursive)
    {
    }

    /**
     * Default implementation for the getDirectTransitionImpl() method.
     * @param context A pointer to the containing state machine.
     * @param nextState Receives a pointer to the next sibling state to appear on a direct transition.
     * @param finalize Receives \c true to finalize the containing state machine.
     * @return \c true if a direct transition should be performed, \c false otherwise.
     */
    bool checkDirectTransitionImpl(Context* context, bool& finalize, StateBaseType*& nextState)
    {
        nextState = 0;
        finalize = false;
        return false;
    }

protected:
    /**
     * Constructor for class State.
     *
     * @param argDoAction A pointer to the state do action.
     */
    State(StateDoAction argDoAction = 0)
    : doAction(argDoAction)
    {
    }

    /**
     * Destructor for class State.
     */
    virtual ~State()
    {
    }

    /**
     * Changes \em context state machine to another sibling state.
     * @param context A pointer to the containing state machine.
     * @param newState A pointer to the sibling state to change to.
     */
    void changeState(Context* context,StateBaseType* newState)
    {
        static_cast<Implementation*>(this)->changeStateImpl(context,newState);
    }

    /**
     * Changes \em context state machine to another sibling state.
     * @param context A pointer to the containing state machine.
     * @param newState A pointer to the sibling state to change to.
     */
    template<class StateMachineContext>
    void changeState(StateMachineContext* context,StateBaseType* newState)
    {
        static_cast<Implementation*>(this)->changeStateImpl(context,newState);
    }

    /**
     * The state do action.
     */
    StateDoAction doAction;

private:
    virtual void entry(Context* context)
    {
        static_cast<Implementation*>(this)->entryImpl(context);
    }

    virtual void exit(Context* context)
    {
        static_cast<Implementation*>(this)->exitImpl(context);
    }

//    template<class StateMachineContext>
//    virtual void entry(StateMachineContext* context)
//    {
//        static_cast<Implementation*>(this)->entryImpl(context);
//    }
//
//    template<class StateMachineContext>
//    virtual void exit(StateMachineContext* context)
//    {
//        static_cast<Implementation*>(this)->exitImpl(context);
//    }

    virtual void startDo(Context* context)
    {
        // Run the do action
        static_cast<Implementation*>(this)->startDoImpl(context);

        // Handle direct transitions
        StateBaseType* nextState = 0;
        bool finalize = false;
        if(static_cast<Implementation*>(this)->checkDirectTransitionImpl(context,finalize,nextState))
        {
            if(finalize)
            {
                context->finalize();
            }
            else if(nextState)
            {
                changeState(context,nextState);
            }
        }
    }

    virtual void endDo(Context* context)
    {
        static_cast<Implementation*>(this)->endDoImpl(context);
    }

    virtual void joinDoAction(Context* context)
    {
        static_cast<Implementation*>(this)->joinDoActionImpl(context);
    }

    virtual void finalizeSubStateMachines(bool recursive)
    {
        static_cast<Implementation*>(this)->finalizeSubStateMachinesImpl(recursive);
    }

    virtual void initSubStateMachines(bool recursive)
    {
        static_cast<Implementation*>(this)->initSubStateMachinesImpl(recursive);
    }

};
}

#endif /* STATE_H_ */

SttclConfig.h

/*
 * SttclConfig.h
 *
 *  Created on: 13.03.2013
 *      Author: Admin
 */

#ifndef STTCLCONFIG_H_
#define STTCLCONFIG_H_

#define STTCL_USE_STL
#define STTCL_THREADSAFE_IMPL

#define STTCL_HAVE_RTTI
#define STTCL_HAVE_HIGHRES_CLOCK

#if defined(__GXX_EXPERIMENTAL_CXX0X__)
#if defined(STTCL_HAVE_HIGHRES_CLOCK)
#define _GLIBCXX_USE_NANOSLEEP
#endif
#endif

#if defined(STTCL_POSIX_IMPL)
#if defined(STTCL_HAVE_HIGHRES_CLOCK)
#define STTCL_POSIX_NANOSLEEP
#endif
#endif

#if defined(STTCL_THREADSAFE_IMPL)
#include "SttclMutex.h"
#endif

#if defined(STTCL_THREADSAFE_IMPL) && !defined(STTCL_STATEMACHINE_SAFE_RETURN)
#define STTCL_STATEMACHINE_SAFE_RETURN(internalLockGuard,_ReturnValue_) \
        sttcl::internal::AutoLocker<StateMachineMutexType> lock(internalLockGuard); \
        return (_ReturnValue_);
#else
#define STTCL_STATEMACHINE_SAFE_RETURN(internalLockGuard,_ReturnValue_)
#endif

#if defined(STTCL_THREADSAFE_IMPL) && !defined(STTCL_STATEMACHINE_SAFESECTION_START)
#define STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard) \
        { sttcl::internal::AutoLocker<StateMachineMutexType> lock(internalLockGuard);
#else
#define STTCL_STATEMACHINE_SAFESECTION_START(internalLockGuard)
#endif

#if defined(STTCL_THREADSAFE_IMPL) && !defined(STTCL_STATEMACHINE_SAFESECTION_END)
#define STTCL_STATEMACHINE_SAFESECTION_END \
        }
#else
#define STTCL_STATEMACHINE_SAFESECTION_END
#endif

#endif /* STTCLCONFIG_H_ */

For an example of usage refer to Demo1 please.


Proceed to Part II: Abstraction of asynchronous/concurrency features

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.