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
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
00582 virtual RTC::ReturnCode_t bindComponent(RTObject_impl* rtc);
00583
00614 virtual ReturnCode_t remove_component(LightweightRTObject_ptr comp)
00615 throw (CORBA::SystemException);
00616
00636 virtual ExecutionContextProfile* get_profile(void)
00637 throw (CORBA::SystemException);
00638
00639 protected:
00640
00641
00642
00643 typedef LifeCycleState ExecContextState;
00644
00645
00646
00647
00648
00649
00650
00651
00652 typedef RTC_Utils::StateHolder<ExecContextState> ECStates;
00653
00674 class DFPBase
00675 {
00676 public:
00677
00695 DFPBase(RTC::ExecutionContextHandle_t id)
00696 : ec_id(id), m_sm(NUM_OF_LIFECYCLESTATE)
00697 {
00698 m_sm.setListener(this);
00699 m_sm.setEntryAction (ACTIVE_STATE, &DFPBase::on_activated);
00700 m_sm.setDoAction (ACTIVE_STATE, &DFPBase::on_execute);
00701 m_sm.setPostDoAction(ACTIVE_STATE, &DFPBase::on_state_update);
00702 m_sm.setExitAction (ACTIVE_STATE, &DFPBase::on_deactivated);
00703 m_sm.setEntryAction (ERROR_STATE, &DFPBase::on_aborting);
00704 m_sm.setDoAction (ERROR_STATE, &DFPBase::on_error);
00705 m_sm.setExitAction (ERROR_STATE, &DFPBase::on_reset);
00706
00707 ECStates st;
00708 st.prev = INACTIVE_STATE;
00709 st.curr = INACTIVE_STATE;
00710 st.next = INACTIVE_STATE;
00711 m_sm.setStartState(st);
00712 m_sm.goTo(INACTIVE_STATE);
00713 }
00714
00728 virtual ~DFPBase(void){}
00729
00746 virtual void on_startup(void) = 0;
00747
00764 virtual void on_shutdown(void) = 0;
00765
00787 virtual void on_activated(const ECStates& st) = 0;
00788
00810 virtual void on_deactivated(const ECStates& st) = 0;
00811
00833 virtual void on_aborting(const ECStates& st) = 0;
00834
00860 virtual void on_error(const ECStates& st) = 0;
00861
00887 virtual void on_reset(const ECStates& st) = 0;
00888
00915 virtual void on_execute(const ECStates& st) = 0;
00916
00943 virtual void on_state_update(const ECStates& st) = 0;
00944
00962 virtual void on_rate_changed(void) = 0;
00963
00982 virtual void worker(void) {return m_sm.worker();}
00983
01001 virtual ExecContextState get_state(void){ return m_sm.getState();}
01002
01010 ExecutionContextHandle_t ec_id;
01011
01019 RTC_Utils::StateMachine<ExecContextState, DFPBase> m_sm;
01020 };
01021
01022
01023
01024
01050 template <class Object>
01051 class DFP
01052 : public DFPBase
01053 {
01054 public:
01074 DFP(Object obj, ExecutionContextHandle_t id)
01075 : DFPBase(id), m_obj(obj), m_active(true)
01076 {
01077 }
01078
01094 void on_startup(void)
01095 {
01096 m_obj->on_startup(ec_id);
01097 }
01098
01114 void on_shutdown(void)
01115 {
01116 m_obj->on_shutdown(ec_id);
01117 }
01118
01141 void on_activated(const ECStates& st)
01142 {
01143 if (m_obj->on_activated(ec_id) != RTC::RTC_OK)
01144 {
01145 m_sm.goTo(ERROR_STATE);
01146 return;
01147 }
01148 return;
01149 }
01150
01171 void on_deactivated(const ECStates& st)
01172 {
01173 m_obj->on_deactivated(ec_id);
01174 }
01175
01195 void on_aborting(const ECStates& st)
01196 {
01197 m_obj->on_aborting(ec_id);
01198 }
01199
01219 void on_error(const ECStates& st)
01220 {
01221 m_obj->on_error(ec_id);
01222 }
01223
01243 void on_reset(const ECStates& st)
01244 {
01245 if (m_obj->on_reset(ec_id) != RTC::RTC_OK)
01246 {
01247 m_sm.goTo(ERROR_STATE);
01248 return;
01249 }
01250 return;
01251 }
01252
01278 void on_execute(const ECStates& st)
01279 {
01280 if (m_obj->on_execute(ec_id) != RTC::RTC_OK)
01281 {
01282 m_sm.goTo(ERROR_STATE);
01283 return;
01284 }
01285 return;
01286 }
01287
01313 void on_state_update(const ECStates& st)
01314 {
01315 if (m_obj->on_state_update(ec_id) != RTC::RTC_OK)
01316 {
01317 m_sm.goTo(ERROR_STATE);
01318 return;
01319 }
01320 return;
01321 }
01322
01339 void on_rate_changed(void)
01340 {
01341 m_obj->on_rate_changed(ec_id);
01342 }
01343
01351 Object m_obj;
01352
01360 bool m_active;
01361 };
01362
01370 struct Comp
01371 {
01372 Comp(LightweightRTObject_ptr ref, OpenRTM::DataFlowComponent_ptr dfp,
01373 ExecutionContextHandle_t id)
01374 : _ref(LightweightRTObject::_duplicate(ref)),
01375 _sm(OpenRTM::DataFlowComponent::_duplicate(dfp), id)
01376 {
01377 }
01378 ~Comp(void)
01379 {
01380 }
01381 Comp(const Comp& comp)
01382 : _ref(comp._ref), _sm(comp._sm.m_obj, comp._sm.ec_id)
01383 {
01384 }
01385 Comp& operator=(const Comp& comp)
01386 {
01387 _ref = comp._ref;
01388 _sm.m_obj = comp._sm.m_obj;
01389 _sm.ec_id = comp._sm.ec_id;
01390 return *this;
01391 }
01392 LightweightRTObject_var _ref;
01393 DFP<OpenRTM::DataFlowComponent_var> _sm;
01394 };
01395
01403 struct find_comp
01404 {
01405 LightweightRTObject_var m_comp;
01406 find_comp(LightweightRTObject_ptr comp) : m_comp(LightweightRTObject::_duplicate(comp)) {}
01407 bool operator()(Comp& comp)
01408 {
01409 return comp._ref->_is_equivalent(m_comp);
01410 }
01411 };
01412
01420 struct invoke_on_startup
01421 {
01422 void operator()(Comp& comp)
01423 {
01424 comp._sm.on_startup();
01425 }
01426 };
01427
01435 struct invoke_on_shutdown
01436 {
01437 void operator()(Comp& comp)
01438 {
01439 comp._sm.on_shutdown();
01440 }
01441 };
01442
01450 struct invoke_on_rate_changed
01451 {
01452 void operator()(Comp& comp)
01453 {
01454 comp._sm.on_rate_changed();
01455 }
01456 };
01457
01465 struct invoke_worker
01466 {
01467 void operator()(Comp& comp)
01468 {
01469 comp._sm.worker();
01470 }
01471 };
01472
01480 std::vector<Comp> m_comps;
01481 typedef std::vector<Comp>::iterator CompItr;
01482
01490 Logger rtclog;
01491
01501 bool m_running;
01502
01510 bool m_svc;
01511
01512 struct Worker
01513 {
01514 Worker() : cond_(mutex_), running_(false) {};
01515 coil::Mutex mutex_;
01516 coil::Condition<coil::Mutex> cond_;
01517 bool running_;
01518 };
01526
01527 Worker m_worker;
01528
01536 ExecutionContextProfile m_profile;
01537
01545 coil::TimeValue m_period;
01546
01554 ExecutionContextService_var m_ref;
01555
01564 bool m_nowait;
01565 };
01566 };
01567
01568 #ifdef WIN32
01569 #pragma warning( default : 4290 )
01570 #endif
01571
01572
01573 extern "C"
01574 {
01575 void PeriodicExecutionContextInit(RTC::Manager* manager);
01576 };
01577
01578 #endif // RTC_PERIODICEXECUTIONCONTEXT_H