// Copyright 2008 Christophe Henry // henry UNDERSCORE christophe AT hotmail DOT com // This is an extended version of the state machine available in the boost::mpl library // Distributed under the same license as the original. // Copyright for the original version: // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed // under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MSM_BACK_HISTORY_POLICIES_H #define BOOST_MSM_BACK_HISTORY_POLICIES_H #include <boost/mpl/contains.hpp> namespace boost { namespace msm { namespace back { // policy classes // Default: no history used template <int NumberOfRegions> class NoHistoryImpl { public: NoHistoryImpl(){} ~NoHistoryImpl(){} void set_initial_states(int* const initial_states) { for (int i=0;i<NumberOfRegions;++i) m_initialStates[i] = initial_states[i]; } void history_exit(int* const ) { // ignore } // returns the state where the state machine should be at start template <class Event> const int* history_entry(Event const& ) { // always come back to the original state return m_initialStates; } NoHistoryImpl<NumberOfRegions>& operator=(NoHistoryImpl<NumberOfRegions> const& rhs) { for (int i=0; i<NumberOfRegions;++i) { m_initialStates[i] = rhs.m_initialStates[i]; } return *this; } // this policy deletes all waiting deferred events template <class Event> bool process_deferred_events(Event const&)const { return false; } template<class Archive> void serialize(Archive & ar, const unsigned int) { ar & m_initialStates; } private: int m_initialStates[NumberOfRegions]; }; // not UML standard. Always activates history, no matter which event generated the transition template <int NumberOfRegions> class AlwaysHistoryImpl { public: AlwaysHistoryImpl(){} ~AlwaysHistoryImpl(){} void set_initial_states(int* const initial_states) { for (int i=0;i<NumberOfRegions;++i) m_initialStates[i] = initial_states[i]; } void history_exit(int* const current_states) { for (int i=0;i<NumberOfRegions;++i) m_initialStates[i] = current_states[i]; } // returns the state where the state machine should be at start template <class Event> const int* history_entry(Event const& ) { // always load back the last active state return m_initialStates; } AlwaysHistoryImpl<NumberOfRegions>& operator=(AlwaysHistoryImpl<NumberOfRegions> const& rhs) { for (int i=0; i<NumberOfRegions;++i) { m_initialStates[i] = rhs.m_initialStates[i]; } return *this; } // the history policy keeps all deferred events until next reentry template <class Event> bool process_deferred_events(Event const&)const { return true; } template<class Archive> void serialize(Archive & ar, const unsigned int) { ar & m_initialStates; } private: int m_initialStates[NumberOfRegions]; }; // UML Shallow history. For deep history, just use this policy for all the contained state machines template <class Events,int NumberOfRegions> class ShallowHistoryImpl { public: ShallowHistoryImpl(){} ~ShallowHistoryImpl(){} void set_initial_states(int* const initial_states) { for (int i=0;i<NumberOfRegions;++i) { m_currentStates[i] = initial_states[i]; m_initialStates[i] = initial_states[i]; } } void history_exit(int* const current_states) { for (int i=0;i<NumberOfRegions;++i) m_currentStates[i] = current_states[i]; } // returns the state where the state machine should be at start template <class Event> const int* history_entry(Event const&) { if ( ::boost::mpl::contains<Events,Event>::value) { return m_currentStates; } // not one of our events, no history return m_initialStates; } ShallowHistoryImpl<Events,NumberOfRegions>& operator=(ShallowHistoryImpl<Events,NumberOfRegions> const& rhs) { for (int i=0; i<NumberOfRegions;++i) { m_initialStates[i] = rhs.m_initialStates[i]; m_currentStates[i] = rhs.m_currentStates[i]; } return *this; } // the history policy keeps deferred events until next reentry if coming from our history event template <class Event> bool process_deferred_events(Event const&)const { return ::boost::mpl::contains<Events,Event>::value; } template<class Archive> void serialize(Archive & ar, const unsigned int) { ar & m_initialStates; ar & m_currentStates; } private: int m_initialStates[NumberOfRegions]; int m_currentStates[NumberOfRegions]; }; struct NoHistory { typedef int history_policy; template <int NumberOfRegions> struct apply { typedef NoHistoryImpl<NumberOfRegions> type; }; }; struct AlwaysHistory { typedef int history_policy; template <int NumberOfRegions> struct apply { typedef AlwaysHistoryImpl<NumberOfRegions> type; }; }; template <class Events> struct ShallowHistory { typedef int history_policy; template <int NumberOfRegions> struct apply { typedef ShallowHistoryImpl<Events,NumberOfRegions> type; }; }; } } }//boost::msm::back #endif //BOOST_MSM_BACK_HISTORY_POLICIES_H