00001
00002
00003
00004
00005
00006
00007
00008 #ifndef DECISION_MAKING_FSM_H_
00009 #define DECISION_MAKING_FSM_H_
00010
00011
00012 #include "EventSystem.h"
00013 #include "TaskResult.h"
00014
00015 #ifndef DMDEBUG
00016 #define DMDEBUG(...)
00017 #endif
00018
00019
00020 namespace decision_making{
00021
00022 class ___ABS__ScoppedThreadsOnExit{
00023 public:
00024 virtual ~___ABS__ScoppedThreadsOnExit(){}
00025 virtual void exit()=0;
00026 virtual boost::thread_group& getThreads()=0;
00027 };
00028 struct ScoppedThreads{
00029 typedef boost::shared_ptr<EventQueue> EventQueuePtr;
00030 typedef boost::shared_ptr<CallContext> CallContextPtr;
00031 typedef boost::shared_ptr<___ABS__ScoppedThreadsOnExit> ScoppedThreadsOnExitPtr;
00032 boost::thread_group threads;
00033 vector<EventQueuePtr> events;
00034 vector<CallContextPtr> contexts;
00035 void add(boost::thread* thread){threads.add_thread(thread);};
00036 void add(EventQueuePtr event){ events.push_back(event); }
00037 void add(CallContextPtr event){ contexts.push_back(event); }
00038
00039 void stopEvents(){
00040 BOOST_FOREACH(EventQueuePtr e, events){
00041 e->close();
00042 }
00043 }
00044 struct Cleaner{
00045 ScoppedThreads& target;
00046 Cleaner(ScoppedThreads& target):target(target){}
00047 ~Cleaner(){
00048 target.runOnExit();
00049 target.stopEvents();
00050 target.threads.join_all();
00051 }
00052 };
00053
00054 vector<ScoppedThreadsOnExitPtr> on_exits;
00055 void add(ScoppedThreadsOnExitPtr exit){ on_exits.push_back(exit); }
00056
00057 void runOnExit(){
00058 BOOST_FOREACH(ScoppedThreadsOnExitPtr e, on_exits){
00059 e->exit();
00060 e->getThreads().join_all();
00061 }
00062 }
00063 };
00064 class ScoppedThreadsOnExit:public ___ABS__ScoppedThreadsOnExit{
00065 public:
00066 EventQueue* events_queue;
00067 CallContext& state_call_ctx;
00068 ScoppedThreads SUBMACHINESTHREADS;
00069 ScoppedThreadsOnExit(CallContext& call_ctx, EventQueue* events_queue):
00070 events_queue(events_queue), state_call_ctx(call_ctx)
00071 {}
00072 virtual ~ScoppedThreadsOnExit(){}
00073
00074 virtual boost::thread_group& getThreads(){ return SUBMACHINESTHREADS.threads; }
00075 };
00076
00077
00078 #define FSM_HEADER(NAME) \
00079 decision_making::TaskResult Fsm##NAME(const decision_making::CallContext*, decision_making::EventQueue*, std::string);\
00080 decision_making::TaskResult Fsm##NAME(const decision_making::CallContext* p, decision_making::EventQueue* q);
00081
00082 #define FSM(NAME) \
00083 FSM_HEADER(NAME)\
00084 decision_making::TaskResult Fsm##NAME(const decision_making::CallContext* p, decision_making::EventQueue* q){return Fsm##NAME(p,q,#NAME);}\
00085 decision_making::TaskResult Fsm##NAME(const decision_making::CallContext* parent_call_ctx, decision_making::EventQueue* parent_event_queue, std::string fsm_name)
00086
00087 #define FSM_STATES enum STATES
00088
00089 #define __DEFCALLCONTEXT decision_making::CallContext call_ctx(parent_call_ctx?decision_making::CallContext(*parent_call_ctx, fsm_name):decision_making::CallContext(fsm_name));
00090 #define __DEFEVENTQUEUE decision_making::EventQueue* events_queue(parent_event_queue);
00091 #define FSM_START(STATE) \
00092 state ( STATE ); \
00093 decision_making::TaskResult fsm_result = decision_making::TaskResult::TERMINATED();\
00094 __DEFCALLCONTEXT __DEFEVENTQUEUE \
00095 DMDEBUG( cout<<" FSM("<<fsm_name<<":START) "; )\
00096 ON_FSM_START(fsm_name, call_ctx, *events_queue);
00097
00098 #define FSM_BGN \
00099 bool fsm_stop = false; \
00100 while(not fsm_stop and not events_queue->isTerminated() DM_SYSTEM_STOP){ \
00101 switch(state){ { {
00102
00103 #define FSM_END \
00104 }}}} \
00105 DMDEBUG( cout<<" FSM("<<fsm_name<<":FINISH) "; ) \
00106 ON_FSM_END(fsm_name, call_ctx, *events_queue, fsm_result);\
00107 return fsm_result;
00108
00109 #define __STARTOFSTATE(X) \
00110 DMDEBUG( string outname("STT("+fsm_name+":"+call_ctx.str()+"/"+#X+")");cout<<outname<<"{ "; )\
00111 std::string state_name(#X);\
00112 decision_making::CallContext state_call_ctx(call_ctx, state_name);\
00113 ON_FSM_STATE_START(state_name, call_ctx, *events_queue);
00114
00115 #define __ENDOFSTATE \
00116 DMDEBUG( struct _STATE_FINISHER_PRINT{std::string n;_STATE_FINISHER_PRINT( std::string n): n(n){}~_STATE_FINISHER_PRINT(){DMDEBUG( cout<<"}"<<n<<" "; )} void r(){}}_ep(outname);_ep.r(); )\
00117 struct _STATE_FINISHER{\
00118 std::string state_name; decision_making::CallContext& ctx; decision_making::EventQueue& queue;\
00119 _STATE_FINISHER(std::string state_name, decision_making::CallContext& ctx, decision_making::EventQueue& queue): state_name(state_name),ctx(ctx),queue(queue){}\
00120 ~_STATE_FINISHER(){\
00121 ON_FSM_STATE_END(state_name, ctx, queue);\
00122 } void r(){}\
00123 }_e(state_name, call_ctx, *events_queue);_e.r();
00124
00125 #define FSM_CONTEXT state_call_ctx
00126
00127 #define FSM_STATE(X) \
00128 }}}break; \
00129 case X: { \
00130 decision_making::ScoppedThreads SUBMACHINESTHREADS; \
00131 __STARTOFSTATE(X) __ENDOFSTATE
00132
00133 #define FSM_NEXT(STATE) \
00134 state = STATE; \
00135 break;
00136 #define FSM_ON_EVENT(EVENT, DO) \
00137 if(event==decision_making::Event(EVENT,state_call_ctx)){ \
00138 DMDEBUG( cout<<" GOTO("<<fsm_name<<":"<<decision_making::Event(EVENT,call_ctx)<< "->" #DO ") "; ) \
00139 DO;\
00140 }
00141 #define FSM_EVENT(EVENT) decision_making::Event(#EVENT,state_call_ctx))
00142
00143 #define FSM_ON_CONDITION(COND, DO) \
00144 if(COND){ \
00145 DMDEBUG( cout<<" GOTO("<<fsm_name<<":"<<decision_making::Event(#COND,state_call_ctx)<< "->" #DO ") "; ) \
00146 DO;\
00147 }
00148
00149 #define FSM_RAISE(EVENT) \
00150 DMDEBUG( cout<<" RAISE("<<fsm_name<<":"<<decision_making::Event(EVENT, state_call_ctx)<<") "; ) \
00151 events_queue->raiseEvent(decision_making::Event(EVENT, state_call_ctx));
00152
00153
00154 #define FSM_RISE(EVENT) FSM_RAISE(EVENT)
00155
00156 #define FSM_EVENTS_DROP events_queue->drop_all();
00157
00158 #define __DEFSUBEVENTQUEUE(TASK) decision_making::ScoppedThreads::EventQueuePtr events_queu##TASK( new decision_making::EventQueue(events_queue) );
00159 #define __DEFSUBCTEXT(TASK) decision_making::ScoppedThreads::CallContextPtr call_ctx##TASK( new decision_making::CallContext(state_call_ctx, #TASK) );
00160 #define __SHR_TO_REF(X) (*(X.get()))
00161 #define FSM_CALL_TASK(TASK) \
00162 __DEFSUBEVENTQUEUE(TASK) __DEFSUBCTEXT(TASK) \
00163 SUBMACHINESTHREADS.add(events_queu##TASK); \
00164 SUBMACHINESTHREADS.add(call_ctx##TASK); \
00165 SUBMACHINESTHREADS.add(\
00166 new boost::thread( CALL_REMOTE(TASK, boost::ref(__SHR_TO_REF(call_ctx##TASK)), boost::ref(__SHR_TO_REF(events_queu##TASK))) ));
00167
00168 #define FSM_CALL_FSM(NAME) \
00169 __DEFSUBEVENTQUEUE(NAME) \
00170 SUBMACHINESTHREADS.add(events_queu##NAME); \
00171 SUBMACHINESTHREADS.add(\
00172 new boost::thread(boost::bind(&Fsm##NAME, &state_call_ctx, events_queu##NAME.get()) ));
00173
00174
00175 #define FSM_CALL_BT(NAME) \
00176 __DEFSUBEVENTQUEUE(NAME) __DEFSUBCTEXT(NAME) \
00177 SUBMACHINESTHREADS.add(events_queu##NAME); \
00178 SUBMACHINESTHREADS.add(call_ctx##NAME); \
00179 decision_making::EventQueue& __t_events_queu##NAME = __SHR_TO_REF(events_queu##NAME);\
00180 decision_making::CallContext& __t_call_ctx##NAME = __SHR_TO_REF(call_ctx##NAME);\
00181 __BT_CREATE_BT_CALL_FUNCTION(NAME, __t_call_ctx##NAME, __t_events_queu##NAME)\
00182 SUBMACHINESTHREADS.add(\
00183 __CALL_BT_FUNCTION(NAME, boost::ref(__t_call_ctx##NAME), boost::ref(__t_events_queu##NAME)) \
00184 );
00185
00186 #define FSM_ON_STATE_EXIT_BGN \
00187 class __ON_STATE_EXIT_STRUCT:public decision_making::ScoppedThreadsOnExit{public:\
00188 __ON_STATE_EXIT_STRUCT(CallContext& state_call_ctx, EventQueue* events_queue):decision_making::ScoppedThreadsOnExit(state_call_ctx, events_queue){}\
00189 virtual void exit(){
00190
00191 #define FSM_ON_STATE_EXIT_END \
00192 }\
00193 };\
00194 decision_making::ScoppedThreadsOnExit* __tmp___ON_STATE_EXIT_STRUCT = new __ON_STATE_EXIT_STRUCT(state_call_ctx, events_queue);\
00195 SUBMACHINESTHREADS.add(decision_making::ScoppedThreads::ScoppedThreadsOnExitPtr(__tmp___ON_STATE_EXIT_STRUCT));
00196
00197 #define FSM_ON_STATE_EXIT(...) } __VA_ARGS__ {
00198
00199 #define FSM_STOP(EVENT, RESULT) \
00200 fsm_stop=true; \
00201 FSM_RAISE(EVENT); \
00202 fsm_result = RESULT; \
00203 break;
00204
00205 #define __CLEAN_THREAD_AND_EVENTS decision_making::ScoppedThreads::Cleaner SUBMACHINESTHREADSCLEANER(SUBMACHINESTHREADS);
00206 #define FSM_TRANSITIONS __CLEAN_THREAD_AND_EVENTS {Event event; while((event=events_queue->waitEvent())==true){
00207
00208 #define FSM_DROP_EVENTS events_queue->drop_all();
00209
00210 #define FSM_PRINT_EVENT if(not event.equals(decision_making::Event::SPIN_EVENT())){ cout<<" READ("<<fsm_name<<":"<<event<<") "; }
00211
00212 }
00213
00214
00215 #endif