FSM.h
Go to the documentation of this file.
00001 /*
00002  * FSM.h
00003  *
00004  *  Created on: Nov 14, 2013
00005  *      Author: dan
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         //void runOnExit();
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         //virtual void exit()=0;
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 //Deprecated
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 /* FSM_H_ */


decision_making
Author(s):
autogenerated on Wed Aug 26 2015 11:16:53