00001
00020 #ifndef RTC_PERIODICEXECUTIONCONTEXT_H
00021 #define RTC_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 #define NUM_OF_LIFECYCLESTATE 4
00037
00038 #ifdef WIN32
00039 #pragma warning( disable : 4290 )
00040 #endif
00041
00042 namespace RTC
00043 {
00064 class PeriodicExecutionContext
00065 : public virtual ExecutionContextBase,
00066 public coil::Task
00067 {
00068 public:
00088 PeriodicExecutionContext();
00089
00111 PeriodicExecutionContext(OpenRTM::DataFlowComponent_ptr owner,
00112 double rate = 1000.0);
00113
00127 virtual ~PeriodicExecutionContext(void);
00128
00148 virtual ExecutionContextService_ptr getObjRef(void) {return m_ref;}
00149
00174 virtual int open(void *args);
00175
00195 virtual int svc(void);
00196
00224 virtual int close(unsigned long flags);
00225
00226
00227
00228
00253 virtual CORBA::Boolean is_running(void)
00254 throw (CORBA::SystemException);
00255
00283 virtual ReturnCode_t start(void)
00284 throw (CORBA::SystemException);
00285
00312 virtual ReturnCode_t stop(void)
00313 throw (CORBA::SystemException);
00314
00335 virtual CORBA::Double get_rate(void)
00336 throw (CORBA::SystemException);
00337
00367 virtual ReturnCode_t set_rate(CORBA::Double rate)
00368 throw (CORBA::SystemException);
00369
00403 virtual ReturnCode_t activate_component(LightweightRTObject_ptr comp)
00404 throw (CORBA::SystemException);
00405
00438 virtual ReturnCode_t deactivate_component(LightweightRTObject_ptr comp)
00439 throw (CORBA::SystemException);
00440
00472 virtual ReturnCode_t reset_component(LightweightRTObject_ptr comp)
00473 throw (CORBA::SystemException);
00474
00501 virtual LifeCycleState get_component_state(LightweightRTObject_ptr comp)
00502 throw (CORBA::SystemException);
00503
00523 virtual ExecutionKind get_kind(void)
00524 throw (CORBA::SystemException);
00525
00557 virtual ReturnCode_t add_component(LightweightRTObject_ptr comp)
00558 throw (CORBA::SystemException);
00559
00577 virtual RTC::ReturnCode_t bindComponent(RTObject_impl* rtc);
00578
00609 virtual ReturnCode_t remove_component(LightweightRTObject_ptr comp)
00610 throw (CORBA::SystemException);
00611
00631 virtual ExecutionContextProfile* get_profile(void)
00632 throw (CORBA::SystemException);
00633
00634 protected:
00635
00636
00637
00638 typedef LifeCycleState ExecContextState;
00639
00640
00641
00642
00643
00644
00645
00646
00647 typedef RTC_Utils::StateHolder<ExecContextState> ECStates;
00648
00669 class DFPBase
00670 {
00671 public:
00672
00690 DFPBase(RTC::ExecutionContextHandle_t id)
00691 : ec_id(id), m_sm(NUM_OF_LIFECYCLESTATE)
00692 {
00693 m_sm.setListener(this);
00694 m_sm.setEntryAction (ACTIVE_STATE, &DFPBase::on_activated);
00695 m_sm.setDoAction (ACTIVE_STATE, &DFPBase::on_execute);
00696 m_sm.setPostDoAction(ACTIVE_STATE, &DFPBase::on_state_update);
00697 m_sm.setExitAction (ACTIVE_STATE, &DFPBase::on_deactivated);
00698 m_sm.setEntryAction (ERROR_STATE, &DFPBase::on_aborting);
00699 m_sm.setDoAction (ERROR_STATE, &DFPBase::on_error);
00700 m_sm.setExitAction (ERROR_STATE, &DFPBase::on_reset);
00701
00702 ECStates st;
00703 st.prev = INACTIVE_STATE;
00704 st.curr = INACTIVE_STATE;
00705 st.next = INACTIVE_STATE;
00706 m_sm.setStartState(st);
00707 m_sm.goTo(INACTIVE_STATE);
00708 }
00709
00723 virtual ~DFPBase(void){}
00724
00741 virtual void on_startup(void) = 0;
00742
00759 virtual void on_shutdown(void) = 0;
00760
00782 virtual void on_activated(const ECStates& st) = 0;
00783
00805 virtual void on_deactivated(const ECStates& st) = 0;
00806
00828 virtual void on_aborting(const ECStates& st) = 0;
00829
00855 virtual void on_error(const ECStates& st) = 0;
00856
00882 virtual void on_reset(const ECStates& st) = 0;
00883
00910 virtual void on_execute(const ECStates& st) = 0;
00911
00938 virtual void on_state_update(const ECStates& st) = 0;
00939
00957 virtual void on_rate_changed(void) = 0;
00958
00977 virtual void worker(void) {return m_sm.worker();}
00978
00996 virtual ExecContextState get_state(void){ return m_sm.getState();}
00997
01005 ExecutionContextHandle_t ec_id;
01006
01014 RTC_Utils::StateMachine<ExecContextState, DFPBase> m_sm;
01015 };
01016
01017
01018
01019
01045 template <class Object>
01046 class DFP
01047 : public DFPBase
01048 {
01049 public:
01069 DFP(Object obj, ExecutionContextHandle_t id)
01070 : DFPBase(id), m_obj(obj), m_active(true)
01071 {
01072 }
01073
01089 void on_startup(void)
01090 {
01091 m_obj->on_startup(ec_id);
01092 }
01093
01109 void on_shutdown(void)
01110 {
01111 m_obj->on_shutdown(ec_id);
01112 }
01113
01136 void on_activated(const ECStates& st)
01137 {
01138 if (m_obj->on_activated(ec_id) != RTC::RTC_OK)
01139 {
01140 m_sm.goTo(ERROR_STATE);
01141 return;
01142 }
01143 return;
01144 }
01145
01166 void on_deactivated(const ECStates& st)
01167 {
01168 m_obj->on_deactivated(ec_id);
01169 }
01170
01190 void on_aborting(const ECStates& st)
01191 {
01192 m_obj->on_aborting(ec_id);
01193 }
01194
01214 void on_error(const ECStates& st)
01215 {
01216 m_obj->on_error(ec_id);
01217 }
01218
01238 void on_reset(const ECStates& st)
01239 {
01240 if (m_obj->on_reset(ec_id) != RTC::RTC_OK)
01241 {
01242 m_sm.goTo(ERROR_STATE);
01243 return;
01244 }
01245 return;
01246 }
01247
01273 void on_execute(const ECStates& st)
01274 {
01275 if (m_obj->on_execute(ec_id) != RTC::RTC_OK)
01276 {
01277 m_sm.goTo(ERROR_STATE);
01278 return;
01279 }
01280 return;
01281 }
01282
01308 void on_state_update(const ECStates& st)
01309 {
01310 if (m_obj->on_state_update(ec_id) != RTC::RTC_OK)
01311 {
01312 m_sm.goTo(ERROR_STATE);
01313 return;
01314 }
01315 return;
01316 }
01317
01335 void on_rate_changed(void)
01336 {
01337 m_obj->on_rate_changed(ec_id);
01338 }
01339
01347 Object m_obj;
01348
01356 bool m_active;
01357 };
01358
01366 struct Comp
01367 {
01368 Comp(LightweightRTObject_ptr ref, OpenRTM::DataFlowComponent_ptr dfp,
01369 ExecutionContextHandle_t id)
01370 : _ref(LightweightRTObject::_duplicate(ref)),
01371 _sm(OpenRTM::DataFlowComponent::_duplicate(dfp), id)
01372 {
01373 }
01374 ~Comp(void)
01375 {
01376 }
01377 Comp(const Comp& comp)
01378 : _ref(comp._ref), _sm(comp._sm.m_obj, comp._sm.ec_id)
01379 {
01380 }
01381 Comp& operator=(const Comp& comp)
01382 {
01383 _ref = comp._ref;
01384 _sm.m_obj = comp._sm.m_obj;
01385 _sm.ec_id = comp._sm.ec_id;
01386 return *this;
01387 }
01388 LightweightRTObject_var _ref;
01389 DFP<OpenRTM::DataFlowComponent_var> _sm;
01390 };
01391
01399 struct find_comp
01400 {
01401 LightweightRTObject_var m_comp;
01402 find_comp(LightweightRTObject_ptr comp)
01403 : m_comp(LightweightRTObject::_duplicate(comp)) {}
01404 bool operator()(Comp& comp)
01405 {
01406 return comp._ref->_is_equivalent(m_comp);
01407 }
01408 };
01409
01417 struct invoke_on_startup
01418 {
01419 void operator()(Comp& comp)
01420 {
01421 comp._sm.on_startup();
01422 }
01423 };
01424
01432 struct invoke_on_shutdown
01433 {
01434 void operator()(Comp& comp)
01435 {
01436 comp._sm.on_shutdown();
01437 }
01438 };
01439
01447 struct invoke_on_rate_changed
01448 {
01449 void operator()(Comp& comp)
01450 {
01451 comp._sm.on_rate_changed();
01452 }
01453 };
01454
01462 struct invoke_worker
01463 {
01464 void operator()(Comp& comp)
01465 {
01466 comp._sm.worker();
01467 }
01468 };
01469
01477 std::vector<Comp> m_comps;
01478 typedef std::vector<Comp>::iterator CompItr;
01479
01487 Logger rtclog;
01488
01498 bool m_running;
01499
01507 bool m_svc;
01508
01516 struct Worker
01517 {
01518 Worker() : cond_(mutex_), running_(false) {};
01519 coil::Mutex mutex_;
01520 coil::Condition<coil::Mutex> cond_;
01521 bool running_;
01522 };
01523
01531 Worker m_worker;
01532
01540 ExecutionContextProfile m_profile;
01541
01549 coil::TimeValue m_period;
01550
01558 ExecutionContextService_var m_ref;
01559
01568 bool m_nowait;
01569
01570 class find_participant
01571 {
01572 RTObject_var m_comp;
01573 public:
01574 find_participant(RTObject_ptr comp)
01575 : m_comp(RTObject::_duplicate(comp)) {}
01576 bool operator()(RTObject_ptr comp)
01577 {
01578 return m_comp->_is_equivalent(comp);
01579 }
01580 };
01581 };
01582 };
01583
01584 #ifdef WIN32
01585 #pragma warning( default : 4290 )
01586 #endif
01587
01588
01589 extern "C"
01590 {
01598 void PeriodicExecutionContextInit(RTC::Manager* manager);
01599 };
01600
01601 #endif // RTC_PERIODICEXECUTIONCONTEXT_H