- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gstatemachine.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
20
21 #ifndef G_STATE_MACHINE_H
22 #define G_STATE_MACHINE_H
23
24 #include "gdef.h"
25 #include "gexception.h"
26 #include <map>
27
29 namespace G
30 {
31
32 G_EXCEPTION_CLASS( StateMachine_Error , "invalid state machine transition" ) ;
33
108 template <typename T, typename State, typename Event, typename Arg = std::string>
109 class StateMachine
110 {
111 public:
112 typedef void (T::*Action)(const Arg &, bool &) ;
113 typedef StateMachine_Error Error ;
114
115 StateMachine( State s_start , State s_end , State s_same , State s_any ) ;
117
118 void addTransition( Event event , State from , State to , Action action ) ;
121
122 void addTransition( Event event , State from , State to , Action action , State alt ) ;
126
127 State apply( T & t , Event event , const Arg & arg ) ;
142
143 State state() const ;
145
146 State reset( State new_state ) ;
148
149 private:
151 struct Transition
152 {
153 State from ;
154 State to ;
155 State alt ; // alternate "to" state if predicate false
156 Action action ;
157 Transition(State s1,State s2,Action a,State s3) :
158 from(s1) , to(s2) , alt(s3) , action(a) {}
159 } ;
160 typedef std::multimap<Event,Transition> Map ;
161 typedef typename Map::value_type Map_value_type ;
162 Map m_map ;
163 State m_state ;
164 State m_end ;
165 State m_same ;
166 State m_any ;
167 } ;
168
169 template <typename T, typename State, typename Event, typename Arg>
170 StateMachine<T,State,Event,Arg>::StateMachine( State s_start , State s_end , State s_same , State s_any ) :
171 m_state(s_start) ,
172 m_end(s_end) ,
173 m_same(s_same) ,
174 m_any(s_any)
175 {
176 }
177
178 template <typename T, typename State, typename Event, typename Arg>
179 void StateMachine<T,State,Event,Arg>::addTransition( Event event , State from , State to , Action action )
180 {
181 addTransition( event , from , to , action , to ) ;
182 }
183
184 template <typename T, typename State, typename Event, typename Arg>
185 void StateMachine<T,State,Event,Arg>::addTransition( Event event , State from , State to , Action action , State alt )
186 {
187 if( to == m_any || alt == m_any )
188 throw Error( "\"to any\" is invalid" ) ;
189
190 if( from == m_same )
191 throw Error( "\"from same\" is invalid" ) ;
192
193 if( to == m_end && alt != to )
194 throw Error( "predicates on end-state transitions are invalid" ) ;
195
196 if( alt == m_end && to != m_end )
197 throw Error( "false predicates cannot take you to the end state" ) ;
198
199 m_map.insert( Map_value_type( event , Transition(from,to,action,alt) ) ) ;
200 }
201
202 template <typename T, typename State, typename Event, typename Arg>
203 State StateMachine<T,State,Event,Arg>::reset( State new_state )
204 {
205 State old_state = m_state ;
206 m_state = new_state ;
207 return old_state ;
208 }
209
210 template <typename T, typename State, typename Event, typename Arg>
211 State StateMachine<T,State,Event,Arg>::state() const
212 {
213 return m_state ;
214 }
215
216 template <typename T, typename State, typename Event, typename Arg>
217 State StateMachine<T,State,Event,Arg>::apply( T & t , Event event , const Arg & arg )
218 {
219 State state = m_state ;
220 typename Map::iterator p = m_map.find(event) ; // look up in the multimap keyed on event + current-state
221 for( ; p != m_map.end() && (*p).first == event ; ++p )
222 {
223 if( (*p).second.from == m_any || (*p).second.from == m_state )
224 {
225 State old_state = m_state ; // change state
226 if( (*p).second.to != m_same )
227 state = m_state = (*p).second.to ;
228
229 State end = m_end ; // (avoid using members after the action method call)
230
231 bool predicate = true ;
232 (t.*((*p).second.action))( arg , predicate ) ; // perform action
233
234 if( state != end && !predicate ) // respond to predicate
235 {
236 State alt_state = (*p).second.alt ;
237 state = m_state = alt_state == m_same ? old_state : alt_state ;
238 }
239 return state ;
240 }
241 }
242 return m_any ;
243 }
244
245 }
246
247 #endif
248
G::StateMachine::apply
State apply(T &t, Event event, const Arg &arg)
Applies an event.
Definition: gstatemachine.h:217
G
Low-level classes.
G::StateMachine::StateMachine
StateMachine(State s_start, State s_end, State s_same, State s_any)
Constructor.
Definition: gstatemachine.h:170
gexception.h
G::StateMachine::Error
StateMachine_Error Error
Definition: gstatemachine.h:113
G::Arg
A class which holds a represention of the argc/argv command line array, and supports simple command-l...
Definition: garg.h:46
G::StateMachine::addTransition
void addTransition(Event event, State from, State to, Action action)
Adds a transition.
Definition: gstatemachine.h:179
G::StateMachine::reset
State reset(State new_state)
Sets the current state. Returns the old state.
Definition: gstatemachine.h:203
G::StateMachine::state
State state() const
Returns the current state.
Definition: gstatemachine.h:211
G::StateMachine
A finite state machine class template.
Definition: gstatemachine.h:109
G_EXCEPTION_CLASS
#define G_EXCEPTION_CLASS(class_name, description)
Definition: gexception.h:87
G::StateMachine::Action
void(T::* Action)(const Arg &, bool &)
Definition: gstatemachine.h:112