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 typedef coil::Guard<coil::Mutex> Guard;
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
00225 virtual int close(unsigned long flags);
00226
00227
00228
00229
00254 virtual CORBA::Boolean is_running(void)
00255 throw (CORBA::SystemException);
00256
00284 virtual ReturnCode_t start(void)
00285 throw (CORBA::SystemException);
00286
00313 virtual ReturnCode_t stop(void)
00314 throw (CORBA::SystemException);
00315
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
00404 virtual ReturnCode_t activate_component(LightweightRTObject_ptr comp)
00405 throw (CORBA::SystemException);
00406
00439 virtual ReturnCode_t deactivate_component(LightweightRTObject_ptr comp)
00440 throw (CORBA::SystemException);
00441
00473 virtual ReturnCode_t reset_component(LightweightRTObject_ptr comp)
00474 throw (CORBA::SystemException);
00475
00502 virtual LifeCycleState get_component_state(LightweightRTObject_ptr comp)
00503 throw (CORBA::SystemException);
00504
00524 virtual ExecutionKind get_kind(void)
00525 throw (CORBA::SystemException);
00526
00558 virtual ReturnCode_t add_component(LightweightRTObject_ptr comp)
00559 throw (CORBA::SystemException);
00560
00578 virtual RTC::ReturnCode_t bindComponent(RTObject_impl* rtc);
00579
00610 virtual ReturnCode_t remove_component(LightweightRTObject_ptr comp)
00611 throw (CORBA::SystemException);
00612
00632 virtual ExecutionContextProfile* get_profile(void)
00633 throw (CORBA::SystemException);
00634
00635 protected:
00636
00637
00638
00639 typedef LifeCycleState ExecContextState;
00640
00641
00642
00643
00644
00645
00646
00647
00648 typedef RTC_Utils::StateHolder<ExecContextState> ECStates;
00649
00670 class DFPBase
00671 {
00672 public:
00673
00691 DFPBase(RTC::ExecutionContextHandle_t id)
00692 : ec_id(id), m_sm(NUM_OF_LIFECYCLESTATE)
00693 {
00694 m_sm.setListener(this);
00695 m_sm.setEntryAction (ACTIVE_STATE, &DFPBase::on_activated);
00696 m_sm.setDoAction (ACTIVE_STATE, &DFPBase::on_execute);
00697 m_sm.setPostDoAction(ACTIVE_STATE, &DFPBase::on_state_update);
00698 m_sm.setExitAction (ACTIVE_STATE, &DFPBase::on_deactivated);
00699 m_sm.setEntryAction (ERROR_STATE, &DFPBase::on_aborting);
00700 m_sm.setDoAction (ERROR_STATE, &DFPBase::on_error);
00701 m_sm.setExitAction (ERROR_STATE, &DFPBase::on_reset);
00702
00703 ECStates st;
00704 st.prev = INACTIVE_STATE;
00705 st.curr = INACTIVE_STATE;
00706 st.next = INACTIVE_STATE;
00707 m_sm.setStartState(st);
00708 m_sm.goTo(INACTIVE_STATE);
00709 }
00710
00724 virtual ~DFPBase(void){}
00725
00742 virtual void on_startup(void) = 0;
00743
00760 virtual void on_shutdown(void) = 0;
00761
00783 virtual void on_activated(const ECStates& st) = 0;
00784
00806 virtual void on_deactivated(const ECStates& st) = 0;
00807
00829 virtual void on_aborting(const ECStates& st) = 0;
00830
00856 virtual void on_error(const ECStates& st) = 0;
00857
00883 virtual void on_reset(const ECStates& st) = 0;
00884
00911 virtual void on_execute(const ECStates& st) = 0;
00912
00939 virtual void on_state_update(const ECStates& st) = 0;
00940
00958 virtual void on_rate_changed(void) = 0;
00959
00978 virtual void worker(void) {return m_sm.worker();}
00979
00997 virtual ExecContextState get_state(void){ return m_sm.getState();}
00998
01006 ExecutionContextHandle_t ec_id;
01007
01015 RTC_Utils::StateMachine<ExecContextState, DFPBase> m_sm;
01016 };
01017
01018
01019
01020
01046 template <class Object>
01047 class DFP
01048 : public DFPBase
01049 {
01050 public:
01070 DFP(Object obj, ExecutionContextHandle_t id)
01071 : DFPBase(id), m_obj(obj), m_active(true)
01072 {
01073 }
01074
01090 void on_startup(void)
01091 {
01092 m_obj->on_startup(ec_id);
01093 }
01094
01110 void on_shutdown(void)
01111 {
01112 m_obj->on_shutdown(ec_id);
01113 }
01114
01137 void on_activated(const ECStates& st)
01138 {
01139 if (m_obj->on_activated(ec_id) != RTC::RTC_OK)
01140 {
01141 m_sm.goTo(ERROR_STATE);
01142 return;
01143 }
01144 return;
01145 }
01146
01167 void on_deactivated(const ECStates& st)
01168 {
01169 m_obj->on_deactivated(ec_id);
01170 }
01171
01191 void on_aborting(const ECStates& st)
01192 {
01193 m_obj->on_aborting(ec_id);
01194 }
01195
01215 void on_error(const ECStates& st)
01216 {
01217 m_obj->on_error(ec_id);
01218 }
01219
01239 void on_reset(const ECStates& st)
01240 {
01241 if (m_obj->on_reset(ec_id) != RTC::RTC_OK)
01242 {
01243 m_sm.goTo(ERROR_STATE);
01244 return;
01245 }
01246 return;
01247 }
01248
01274 void on_execute(const ECStates& st)
01275 {
01276 if (m_obj->on_execute(ec_id) != RTC::RTC_OK)
01277 {
01278 m_sm.goTo(ERROR_STATE);
01279 return;
01280 }
01281 return;
01282 }
01283
01309 void on_state_update(const ECStates& st)
01310 {
01311 if (m_obj->on_state_update(ec_id) != RTC::RTC_OK)
01312 {
01313 m_sm.goTo(ERROR_STATE);
01314 return;
01315 }
01316 return;
01317 }
01318
01336 void on_rate_changed(void)
01337 {
01338 m_obj->on_rate_changed(ec_id);
01339 }
01340
01348 Object m_obj;
01349
01357 bool m_active;
01358 };
01359
01367 struct Comp
01368 {
01369 Comp(LightweightRTObject_ptr ref, OpenRTM::DataFlowComponent_ptr dfp,
01370 ExecutionContextHandle_t id)
01371 : _ref(LightweightRTObject::_duplicate(ref)),
01372 _sm(OpenRTM::DataFlowComponent::_duplicate(dfp), id)
01373 {
01374 }
01375 ~Comp(void)
01376 {
01377 }
01378 Comp(const Comp& comp)
01379 : _ref(comp._ref), _sm(comp._sm.m_obj, comp._sm.ec_id)
01380 {
01381 }
01382 Comp& operator=(const Comp& comp)
01383 {
01384 _ref = comp._ref;
01385 _sm.m_obj = comp._sm.m_obj;
01386 _sm.ec_id = comp._sm.ec_id;
01387 return *this;
01388 }
01389 LightweightRTObject_var _ref;
01390 DFP<OpenRTM::DataFlowComponent_var> _sm;
01391 };
01392
01400 struct find_comp
01401 {
01402 LightweightRTObject_var m_comp;
01403 find_comp(LightweightRTObject_ptr comp)
01404 : m_comp(LightweightRTObject::_duplicate(comp)) {}
01405 bool operator()(Comp& comp)
01406 {
01407 return comp._ref->_is_equivalent(m_comp);
01408 }
01409 };
01410
01418 struct invoke_on_startup
01419 {
01420 void operator()(Comp& comp)
01421 {
01422 comp._sm.on_startup();
01423 }
01424 };
01425
01433 struct invoke_on_shutdown
01434 {
01435 void operator()(Comp& comp)
01436 {
01437 comp._sm.on_shutdown();
01438 }
01439 };
01440
01448 struct invoke_on_rate_changed
01449 {
01450 void operator()(Comp& comp)
01451 {
01452 comp._sm.on_rate_changed();
01453 }
01454 };
01455
01463 struct invoke_worker
01464 {
01465 void operator()(Comp& comp)
01466 {
01467 comp._sm.worker();
01468 }
01469 };
01470
01478 std::vector<Comp> m_comps;
01479 typedef std::vector<Comp>::iterator CompItr;
01480
01488 Logger rtclog;
01489
01499 bool m_running;
01500
01508 bool m_svc;
01509
01517 struct Worker
01518 {
01519 Worker() : cond_(mutex_), running_(false) {};
01520 coil::Mutex mutex_;
01521 coil::Condition<coil::Mutex> cond_;
01522 bool running_;
01523 };
01524
01532 Worker m_worker;
01533
01541 ExecutionContextProfile m_profile;
01542 coil::Mutex m_profileMutex;
01543
01551 coil::TimeValue m_period;
01552
01560 ExecutionContextService_var m_ref;
01561
01570 bool m_nowait;
01571
01572 class find_participant
01573 {
01574 RTObject_var m_comp;
01575 public:
01576 find_participant(RTObject_ptr comp)
01577 : m_comp(RTObject::_duplicate(comp)) {}
01578 bool operator()(RTObject_ptr comp)
01579 {
01580 return m_comp->_is_equivalent(comp);
01581 }
01582 };
01583 };
01584 };
01585
01586 #ifdef WIN32
01587 #pragma warning( default : 4290 )
01588 #endif
01589
01590
01591 extern "C"
01592 {
01600 void PeriodicExecutionContextInit(RTC::Manager* manager);
01601 };
01602
01603 #endif // RTC_PERIODICEXECUTIONCONTEXT_H