BWAPI
|
00001 #pragma once 00002 #include "IFSMState.h" 00003 #include "Transition.h" 00004 #include "FSM.h" 00005 #include <boost/tuple/tuple.hpp> 00006 00013 template <class FSM, class DerivedState> 00014 class FSMState : public IFSMState 00015 { 00016 public: 00017 FSMState(FSM &context) 00018 : m_context(context) 00019 , m_earliestNextTransitionFrame(0) 00020 { 00021 } 00022 00023 virtual ~FSMState() 00024 { 00025 } 00026 00027 std::string getName() const 00028 { 00029 // Could be done during compilation ;-) 00030 std::string fullName(typeid(DerivedState).name()); 00031 size_t begin = fullName.find_last_of("::"); 00032 if (begin == std::string::npos) 00033 begin = 0; 00034 else 00035 ++begin; 00036 return fullName.substr(begin); 00037 } 00038 00044 virtual void externalTerminate() 00045 { 00046 onExit(); 00047 } 00048 00052 void onEnter() 00053 { 00054 m_context.setCurrentState(this); 00055 00056 static_cast<DerivedState*>(this)->onEnterImpl(); 00057 00058 if (m_context.isExecuting()) 00059 { 00060 enableTransitions(); 00061 } 00062 } 00063 00069 void onExit() 00070 { 00071 assert(m_context.m_currentState != NULL); 00072 00073 static_cast<DerivedState*>(this)->onExitImpl(); 00074 00075 disableTransitions(); 00076 00077 m_context.onExitState(); 00078 00079 #ifdef _DEBUG_COMPONENT 00080 verifyPendingSubscriptions("ERROR FSMState::onExit(): Make sure to unsubscribe EventHandler \"%s\" from event \"%s\" when the FSM switches states."); 00081 00082 verifyPendingTasks("ERROR FSMState::onExit(): Make sure to deactivate task \"%s\" when the FSM switches states."); 00083 #endif 00084 00085 m_stateExitEvent.raise(); 00086 } 00087 00088 size_t getEarliestNextTransitionFrame() const 00089 { 00090 return m_earliestNextTransitionFrame; 00091 } 00092 00093 void setEarliestNextTransitionFrame(size_t earliestAllowedFrameNumber) 00094 { 00095 m_earliestNextTransitionFrame = earliestAllowedFrameNumber; 00096 } 00097 00098 protected: 00102 template <size_t size> 00103 struct EventsHelper 00104 { 00105 static void activate(const FSMState& state) 00106 { 00107 boost::get<size-1>(static_cast<const DerivedState&>(state).m_events).activate(); 00108 EventsHelper<size-1>::activate(state); 00109 } 00110 static void deactivate(const FSMState& state) 00111 { 00112 boost::get<size-1>(static_cast<const DerivedState&>(state).m_events).deactivate(); 00113 EventsHelper<size-1>::deactivate(state); 00114 } 00115 }; 00119 template <> 00120 struct EventsHelper<0> 00121 { 00122 static void activate(const FSMState&) {} 00123 static void deactivate(const FSMState&) {} 00124 }; 00125 00129 void enableTransitions() 00130 { 00131 EventsHelper<boost::tuples::length<DerivedState::Events>::value>::activate(*this); 00132 } 00133 00137 void disableTransitions() 00138 { 00139 EventsHelper<boost::tuples::length<DerivedState::Events>::value>::deactivate(*this); 00140 } 00141 00142 // Problem: "Events m_events" and "Transitions m_transitions" cannot be stored in here as DerivedType is 00143 // not yet defined in FSMState<DerivedState> (so they must be defined in derived classes instead). 00144 00148 FSM &m_context; 00149 00155 size_t m_earliestNextTransitionFrame; 00156 00157 private: 00158 FSMState(const FSMState& other); 00159 };