00001
00020 #ifndef PeriodicExecutionContext_h
00021 #define PeriodicExecutionContext_h
00022
00023 #include <coil/Task.h>
00024 #include <coil/Mutex.h>
00025 #include <coil/Condition.h>
00026 #include <vector>
00027 #include <iostream>
00028
00029 #include <rtm/RTC.h>
00030 #include <rtm/idl/RTCSkel.h>
00031 #include <rtm/idl/OpenRTMSkel.h>
00032 #include <rtm/Manager.h>
00033 #include <rtm/StateMachine.h>
00034 #include <rtm/ExecutionContextBase.h>
00035
00036
00037 #define NUM_OF_LIFECYCLESTATE 4
00038
00039 #ifdef WIN32
00040 #pragma warning( disable : 4290 )
00041 #endif
00042
00043 namespace RTC
00044 {
00065 class PeriodicExecutionContext
00066 : public virtual ExecutionContextBase,
00067 public coil::Task
00068 {
00069 public:
00089 PeriodicExecutionContext();
00090
00112 PeriodicExecutionContext(OpenRTM::DataFlowComponent_ptr owner,
00113 double rate = 1000.0);
00114
00128 virtual ~PeriodicExecutionContext(void);
00129
00149 virtual ExecutionContextService_ptr getObjRef(void) {return m_ref;}
00150
00175 virtual int open(void *args);
00176
00196 virtual int svc(void);
00197
00224 virtual int close(unsigned long flags);
00225
00226
00227
00228
00253 virtual CORBA::Boolean is_running(void)
00254 throw (CORBA::SystemException);
00255
00284 virtual ReturnCode_t start(void)
00285 throw (CORBA::SystemException);
00286
00314 virtual ReturnCode_t stop(void)
00315 throw (CORBA::SystemException);
00316
00336 virtual CORBA::Double get_rate(void)
00337 throw (CORBA::SystemException);
00338
00368 virtual ReturnCode_t set_rate(CORBA::Double rate)
00369 throw (CORBA::SystemException);
00370
00405 virtual ReturnCode_t activate_component(LightweightRTObject_ptr comp)
00406 throw (CORBA::SystemException);
00407
00441 virtual ReturnCode_t deactivate_component(LightweightRTObject_ptr comp)
00442 throw (CORBA::SystemException);
00443
00476 virtual ReturnCode_t reset_component(LightweightRTObject_ptr comp)
00477 throw (CORBA::SystemException);
00478
00506 virtual LifeCycleState get_component_state(LightweightRTObject_ptr comp)
00507 throw (CORBA::SystemException);
00508
00527 virtual ExecutionKind get_kind(void)
00528 throw (CORBA::SystemException);
00529
00562 virtual ReturnCode_t add_component(LightweightRTObject_ptr comp)
00563 throw (CORBA::SystemException);
00564
00565 virtual RTC::ReturnCode_t bindComponent(RTObject_impl* rtc);
00566
00597 virtual ReturnCode_t remove_component(LightweightRTObject_ptr comp)
00598 throw (CORBA::SystemException);
00599
00619 virtual ExecutionContextProfile* get_profile(void)
00620 throw (CORBA::SystemException);
00621
00622 protected:
00623
00624
00625
00626 typedef LifeCycleState ExecContextState;
00627
00628
00629
00630
00631
00632
00633
00634
00635 typedef RTC_Utils::StateHolder<ExecContextState> ECStates;
00636
00657 class DFPBase
00658 {
00659 public:
00660
00678 DFPBase(RTC::ExecutionContextHandle_t id)
00679 : ec_id(id), m_sm(NUM_OF_LIFECYCLESTATE)
00680 {
00681 m_sm.setListener(this);
00682 m_sm.setEntryAction (ACTIVE_STATE, &DFPBase::on_activated);
00683 m_sm.setDoAction (ACTIVE_STATE, &DFPBase::on_execute);
00684 m_sm.setPostDoAction(ACTIVE_STATE, &DFPBase::on_state_update);
00685 m_sm.setExitAction (ACTIVE_STATE, &DFPBase::on_deactivated);
00686 m_sm.setEntryAction (ERROR_STATE, &DFPBase::on_aborting);
00687 m_sm.setDoAction (ERROR_STATE, &DFPBase::on_error);
00688 m_sm.setExitAction (ERROR_STATE, &DFPBase::on_reset);
00689
00690 ECStates st;
00691 st.prev = INACTIVE_STATE;
00692 st.curr = INACTIVE_STATE;
00693 st.next = INACTIVE_STATE;
00694 m_sm.setStartState(st);
00695 m_sm.goTo(INACTIVE_STATE);
00696 }
00697
00711 virtual ~DFPBase(void){}
00712
00729 virtual void on_startup(void) = 0;
00730
00747 virtual void on_shutdown(void) = 0;
00748
00770 virtual void on_activated(const ECStates& st) = 0;
00771
00793 virtual void on_deactivated(const ECStates& st) = 0;
00794
00816 virtual void on_aborting(const ECStates& st) = 0;
00817
00843 virtual void on_error(const ECStates& st) = 0;
00844
00870 virtual void on_reset(const ECStates& st) = 0;
00871
00898 virtual void on_execute(const ECStates& st) = 0;
00899
00926 virtual void on_state_update(const ECStates& st) = 0;
00927
00945 virtual void on_rate_changed(void) = 0;
00946
00965 virtual void worker(void) {return m_sm.worker();}
00966
00984 virtual ExecContextState get_state(void){ return m_sm.getState();}
00985
00993 ExecutionContextHandle_t ec_id;
00994
01002 RTC_Utils::StateMachine<ExecContextState, DFPBase> m_sm;
01003 };
01004
01005
01006
01007
01033 template <class Object>
01034 class DFP
01035 : public DFPBase
01036 {
01037 public:
01057 DFP(Object obj, ExecutionContextHandle_t id)
01058 : DFPBase(id), m_obj(obj), m_active(true)
01059 {
01060 }
01061
01077 void on_startup(void)
01078 {
01079 m_obj->on_startup(ec_id);
01080 }
01081
01097 void on_shutdown(void)
01098 {
01099 m_obj->on_shutdown(ec_id);
01100 }
01101
01124 void on_activated(const ECStates& st)
01125 {
01126 if (m_obj->on_activated(ec_id) != RTC::RTC_OK)
01127 {
01128 m_sm.goTo(ERROR_STATE);
01129 return;
01130 }
01131 return;
01132 }
01133
01154 void on_deactivated(const ECStates& st)
01155 {
01156 m_obj->on_deactivated(ec_id);
01157 }
01158
01178 void on_aborting(const ECStates& st)
01179 {
01180 m_obj->on_aborting(ec_id);
01181 }
01182
01202 void on_error(const ECStates& st)
01203 {
01204 m_obj->on_error(ec_id);
01205 }
01206
01226 void on_reset(const ECStates& st)
01227 {
01228 if (m_obj->on_reset(ec_id) != RTC::RTC_OK)
01229 {
01230 m_sm.goTo(ERROR_STATE);
01231 return;
01232 }
01233 return;
01234 }
01235
01261 void on_execute(const ECStates& st)
01262 {
01263 if (m_obj->on_execute(ec_id) != RTC::RTC_OK)
01264 {
01265 m_sm.goTo(ERROR_STATE);
01266 return;
01267 }
01268 return;
01269 }
01270
01296 void on_state_update(const ECStates& st)
01297 {
01298 if (m_obj->on_state_update(ec_id) != RTC::RTC_OK)
01299 {
01300 m_sm.goTo(ERROR_STATE);
01301 return;
01302 }
01303 return;
01304 }
01305
01322 void on_rate_changed(void)
01323 {
01324 m_obj->on_rate_changed(ec_id);
01325 }
01326
01334 Object m_obj;
01335
01343 bool m_active;
01344 };
01345
01353 struct Comp
01354 {
01355 Comp(LightweightRTObject_ptr ref, OpenRTM::DataFlowComponent_ptr dfp,
01356 ExecutionContextHandle_t id)
01357 : _ref(ref), _sm(dfp, id)
01358 {
01359 }
01360 ~Comp(void)
01361 {
01362 }
01363 Comp(const Comp& comp)
01364 : _ref(comp._ref), _sm(comp._sm.m_obj, comp._sm.ec_id)
01365 {
01366 }
01367 Comp& operator=(const Comp& comp)
01368 {
01369 _ref = comp._ref;
01370 _sm.m_obj = comp._sm.m_obj;
01371 _sm.ec_id = comp._sm.ec_id;
01372 return *this;
01373 }
01374 LightweightRTObject_var _ref;
01375 DFP<OpenRTM::DataFlowComponent_var> _sm;
01376 };
01377
01385 struct find_comp
01386 {
01387 LightweightRTObject_var m_comp;
01388 find_comp(LightweightRTObject_ptr comp) : m_comp(comp) {}
01389 bool operator()(Comp& comp)
01390 {
01391 return comp._ref->_is_equivalent(m_comp);
01392 }
01393 };
01394
01402 struct invoke_on_startup
01403 {
01404 void operator()(Comp& comp)
01405 {
01406 comp._sm.on_startup();
01407 }
01408 };
01409
01417 struct invoke_on_shutdown
01418 {
01419 void operator()(Comp& comp)
01420 {
01421 comp._sm.on_shutdown();
01422 }
01423 };
01424
01432 struct invoke_on_rate_changed
01433 {
01434 void operator()(Comp& comp)
01435 {
01436 comp._sm.on_rate_changed();
01437 }
01438 };
01439
01447 struct invoke_worker
01448 {
01449 void operator()(Comp& comp)
01450 {
01451 comp._sm.worker();
01452 }
01453 };
01454
01462 std::vector<Comp> m_comps;
01463 typedef std::vector<Comp>::iterator CompItr;
01464
01465 Logger rtclog;
01466
01476 bool m_running;
01477
01485 bool m_svc;
01486
01487 struct Worker
01488 {
01489 Worker() : cond_(mutex_), running_(false) {};
01490 coil::Mutex mutex_;
01491 coil::Condition<coil::Mutex> cond_;
01492 bool running_;
01493 };
01494
01495 Worker m_worker;
01496
01504 ExecutionContextProfile m_profile;
01505
01513 long int m_usec;
01514
01522 ExecutionContextService_var m_ref;
01523
01532 bool m_nowait;
01533 };
01534 };
01535
01536 #ifdef WIN32
01537 #pragma warning( default : 4290 )
01538 #endif
01539
01540
01541 extern "C"
01542 {
01543 void PeriodicExecutionContextInit(RTC::Manager* manager);
01544 };
01545
01546 #endif