From 1f1d68b59ff9578b0b866733dace41b33d30e3fa Mon Sep 17 00:00:00 2001 From: Peter Soetens Date: Thu, 2 Apr 2015 13:31:13 +0200 Subject: [PATCH] activity: cleanups + solve double stepping The implementation always did a Trigger before a Timeout, which caused double cycles. Renamed mtrigger to mtimeout for consistency Made the TaskCore counters attributes Signed-off-by: Peter Soetens --- rtt/Activity.cpp | 46 +++++++++++++++++++++++++-------------------- rtt/Activity.hpp | 4 ++-- rtt/TaskContext.cpp | 4 ++++ 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/rtt/Activity.cpp b/rtt/Activity.cpp index 0c2698bfc..f6e53ec42 100644 --- a/rtt/Activity.cpp +++ b/rtt/Activity.cpp @@ -55,19 +55,19 @@ namespace RTT Activity::Activity(RunnableInterface* _r, const std::string& name ) : ActivityInterface(_r), os::Thread(ORO_SCHED_OTHER, RTT::os::LowestPriority, 0.0, 0, name ), - update_period(0.0), mtrigger(false) + update_period(0.0), mtimeout(false) { } Activity::Activity(int priority, RunnableInterface* r, const std::string& name ) : ActivityInterface(r), os::Thread(ORO_SCHED_RT, priority, 0.0, 0, name ), - update_period(0.0), mtrigger(false) + update_period(0.0), mtimeout(false) { } Activity::Activity(int priority, Seconds period, RunnableInterface* r, const std::string& name ) : ActivityInterface(r), os::Thread(ORO_SCHED_RT, priority, period, 0, name ), - update_period(period), mtrigger(false) + update_period(period), mtimeout(false) { // We pass the requested period to the constructor to not confuse users with log messages. // Then we clear it immediately again in order to force the Thread implementation to @@ -82,7 +82,7 @@ namespace RTT Activity::Activity(int scheduler, int priority, Seconds period, RunnableInterface* r, const std::string& name ) : ActivityInterface(r), os::Thread(scheduler, priority, period, 0, name ), - update_period(period), mtrigger(false) + update_period(period), mtimeout(false) { // We pass the requested period to the constructor to not confuse users with log messages. // Then we clear it immediately again in order to force the Thread implementation to @@ -92,7 +92,7 @@ namespace RTT Activity::Activity(int scheduler, int priority, Seconds period, unsigned cpu_affinity, RunnableInterface* r, const std::string& name ) : ActivityInterface(r), os::Thread(scheduler, priority, period, cpu_affinity, name ), - update_period(period), mtrigger(false) + update_period(period), mtimeout(false) { // We pass the requested period to the constructor to not confuse users with log messages. // Then we clear it immediately again in order to force the Thread implementation to @@ -129,6 +129,8 @@ namespace RTT if (s < 0.0) return false; update_period = s; + // we need to trigger internally to get the period started + trigger(); return true; } @@ -155,7 +157,7 @@ namespace RTT if ( update_period > 0) { return false; } - mtrigger = true; + mtimeout = true; msg_cond.broadcast(); Thread::start(); return true; @@ -176,21 +178,25 @@ namespace RTT wakeup = 0; } - if ( update_period > 0 ) { + // periodic: we flag mtimeout below; non-periodic: we flag mtimeout in trigger() + if (mtimeout) { + // was a timeout() call, or internally generated after wakeup + mtimeout = false; this->step(); - this->work(base::RunnableInterface::Trigger); + this->work(base::RunnableInterface::TimeOut); } else { - if (runner) { - runner->loop(); - runner->work(base::RunnableInterface::Trigger); + // was a trigger() call + if ( update_period > 0 ) { + this->step(); + this->work(base::RunnableInterface::Trigger); + } else { + if (runner) { + runner->loop(); + runner->work(base::RunnableInterface::Trigger); + } } - } - - // periodic: we flag mtrigger below; non-periodic: we flag mtrigger in trigger() - if (mtrigger) { - mtrigger = false; - this->step(); - this->work(base::RunnableInterface::TimeOut); + // if a timeout() was done during work(), we will re-enter + // loop() due to the Thread::start(). } // next, sleep/wait os::MutexLock lock(msg_lock); @@ -199,14 +205,14 @@ namespace RTT return; } else { // If periodic, sleep until wakeup time or a message comes in. - // when wakeup time passed, wait_until will return false and we recalculate wakeup + mtrigger + // when wakeup time passed, wait_until will return false and we recalculate wakeup + mtimeout bool time_elapsed = ! msg_cond.wait_until(msg_lock,wakeup); if (time_elapsed) { // calculate next wakeup point, overruns causes skips: while ( wakeup < os::TimeService::Instance()->getNSecs() ) wakeup = wakeup + Seconds_to_nsecs(update_period); - mtrigger = true; + mtimeout = true; } } if (mstopRequested) { diff --git a/rtt/Activity.hpp b/rtt/Activity.hpp index 2bcfe69c4..b84bb55b3 100644 --- a/rtt/Activity.hpp +++ b/rtt/Activity.hpp @@ -221,9 +221,9 @@ namespace RTT double update_period; /** - * When set to true, a next work is Triggered. + * When set to true, a next cycle will be a TimeOut cycle. */ - bool mtrigger; + bool mtimeout; bool mstopRequested; }; diff --git a/rtt/TaskContext.cpp b/rtt/TaskContext.cpp index cf57fedad..a6cd76328 100644 --- a/rtt/TaskContext.cpp +++ b/rtt/TaskContext.cpp @@ -120,6 +120,10 @@ namespace RTT this->addOperation("loadService", &TaskContext::loadService, this, ClientThread).doc("Loads a service known to RTT into this component.").arg("service_name","The name with which the service is registered by in the PluginLoader."); this->addAttribute("TriggerOnStart",mTriggerOnStart); + this->addAttribute("CycleCounter",mCycleCounter); + this->addAttribute("IOCounter",mIOCounter); + this->addAttribute("TimeOutCounter",mTimeOutCounter); + this->addAttribute("TriggerCounter",mTriggerCounter); // activity runs from the start. if (our_act) our_act->start();