1 // Copyright 2008 Christophe Henry
2 // henry UNDERSCORE christophe AT hotmail DOT com
3 // This is an extended version of the state machine available in the boost::mpl library
4 // Distributed under the same license as the original.
5 // Copyright for the original version:
6 // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
7 // under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 
11 #ifndef BOOST_MSM_BACK_HISTORY_POLICIES_H
12 #define BOOST_MSM_BACK_HISTORY_POLICIES_H
13 
14 #include <boost/mpl/contains.hpp>
15 
16 namespace boost { namespace msm { namespace back
17 {
18 
19 // policy classes
20 
21 // Default: no history used
22 template <int NumberOfRegions>
23 class NoHistoryImpl
24 {
25 public:
NoHistoryImpl()26     NoHistoryImpl(){}
~NoHistoryImpl()27     ~NoHistoryImpl(){}
set_initial_states(int * const initial_states)28     void set_initial_states(int* const initial_states)
29     {
30         for (int i=0;i<NumberOfRegions;++i)
31             m_initialStates[i] = initial_states[i];
32     }
history_exit(int * const)33     void history_exit(int* const )
34     {
35         // ignore
36     }
37     // returns the state where the state machine should be at start
38     template <class Event>
history_entry(Event const &)39     const int* history_entry(Event const& )
40     {
41         // always come back to the original state
42         return m_initialStates;
43     }
operator =(NoHistoryImpl<NumberOfRegions> const & rhs)44     NoHistoryImpl<NumberOfRegions>& operator=(NoHistoryImpl<NumberOfRegions> const& rhs)
45     {
46          for (int i=0; i<NumberOfRegions;++i)
47          {
48              m_initialStates[i] = rhs.m_initialStates[i];
49          }
50          return *this;
51     }
52     // this policy deletes all waiting deferred events
53     template <class Event>
process_deferred_events(Event const &) const54     bool process_deferred_events(Event const&)const
55     {
56         return false;
57     }
58     template<class Archive>
serialize(Archive & ar,const unsigned int)59     void serialize(Archive & ar, const unsigned int)
60     {
61         ar & m_initialStates;
62     }
63 private:
64     int m_initialStates[NumberOfRegions];
65 };
66 
67 // not UML standard. Always activates history, no matter which event generated the transition
68 template <int NumberOfRegions>
69 class AlwaysHistoryImpl
70 {
71 public:
AlwaysHistoryImpl()72     AlwaysHistoryImpl(){}
~AlwaysHistoryImpl()73     ~AlwaysHistoryImpl(){}
set_initial_states(int * const initial_states)74     void set_initial_states(int* const initial_states)
75     {
76         for (int i=0;i<NumberOfRegions;++i)
77             m_initialStates[i] = initial_states[i];
78     }
history_exit(int * const current_states)79     void history_exit(int* const current_states)
80     {
81         for (int i=0;i<NumberOfRegions;++i)
82             m_initialStates[i] = current_states[i];
83     }
84     // returns the state where the state machine should be at start
85     template <class Event>
history_entry(Event const &)86     const int* history_entry(Event const& )
87     {
88         // always load back the last active state
89         return m_initialStates;
90     }
operator =(AlwaysHistoryImpl<NumberOfRegions> const & rhs)91     AlwaysHistoryImpl<NumberOfRegions>& operator=(AlwaysHistoryImpl<NumberOfRegions> const& rhs)
92     {
93          for (int i=0; i<NumberOfRegions;++i)
94          {
95              m_initialStates[i] = rhs.m_initialStates[i];
96          }
97          return *this;
98     }
99     // the history policy keeps all deferred events until next reentry
100     template <class Event>
process_deferred_events(Event const &) const101     bool process_deferred_events(Event const&)const
102     {
103         return true;
104     }
105 
106     template<class Archive>
serialize(Archive & ar,const unsigned int)107     void serialize(Archive & ar, const unsigned int)
108     {
109         ar & m_initialStates;
110     }
111 private:
112     int m_initialStates[NumberOfRegions];
113 };
114 
115 // UML Shallow history. For deep history, just use this policy for all the contained state machines
116 template <class Events,int NumberOfRegions>
117 class ShallowHistoryImpl
118 {
119 public:
ShallowHistoryImpl()120     ShallowHistoryImpl(){}
~ShallowHistoryImpl()121     ~ShallowHistoryImpl(){}
set_initial_states(int * const initial_states)122     void set_initial_states(int* const initial_states)
123     {
124         for (int i=0;i<NumberOfRegions;++i)
125         {
126             m_currentStates[i] = initial_states[i];
127             m_initialStates[i] = initial_states[i];
128         }
129     }
history_exit(int * const current_states)130     void history_exit(int* const current_states)
131     {
132         for (int i=0;i<NumberOfRegions;++i)
133             m_currentStates[i] = current_states[i];
134     }
135     // returns the state where the state machine should be at start
136     template <class Event>
history_entry(Event const &)137     const int* history_entry(Event const&)
138     {
139         if ( ::boost::mpl::contains<Events,Event>::value)
140         {
141             return m_currentStates;
142         }
143         // not one of our events, no history
144         return m_initialStates;
145     }
operator =(ShallowHistoryImpl<Events,NumberOfRegions> const & rhs)146     ShallowHistoryImpl<Events,NumberOfRegions>& operator=(ShallowHistoryImpl<Events,NumberOfRegions> const& rhs)
147     {
148          for (int i=0; i<NumberOfRegions;++i)
149          {
150              m_initialStates[i] = rhs.m_initialStates[i];
151              m_currentStates[i] = rhs.m_currentStates[i];
152          }
153          return *this;
154     }
155     // the history policy keeps deferred events until next reentry if coming from our history event
156     template <class Event>
process_deferred_events(Event const &) const157     bool process_deferred_events(Event const&)const
158     {
159         return ::boost::mpl::contains<Events,Event>::value;
160     }
161     template<class Archive>
serialize(Archive & ar,const unsigned int)162     void serialize(Archive & ar, const unsigned int)
163     {
164         ar & m_initialStates;
165         ar & m_currentStates;
166     }
167 private:
168     int m_initialStates[NumberOfRegions];
169     int m_currentStates[NumberOfRegions];
170 };
171 
172 struct NoHistory
173 {
174     typedef int history_policy;
175     template <int NumberOfRegions>
176     struct apply
177     {
178         typedef NoHistoryImpl<NumberOfRegions> type;
179     };
180 };
181 struct AlwaysHistory
182 {
183     typedef int history_policy;
184     template <int NumberOfRegions>
185     struct apply
186     {
187         typedef AlwaysHistoryImpl<NumberOfRegions> type;
188     };
189 };
190 template <class Events>
191 struct ShallowHistory
192 {
193     typedef int history_policy;
194     template <int NumberOfRegions>
195     struct apply
196     {
197         typedef ShallowHistoryImpl<Events,NumberOfRegions> type;
198     };
199 };
200 } } }//boost::msm::back
201 #endif //BOOST_MSM_BACK_HISTORY_POLICIES_H
202