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