Activity.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Thu Oct 22 11:59:07 CEST 2009 Activity.cpp
3 
4  Activity.cpp - description
5  -------------------
6  begin : Thu October 22 2009
7  copyright : (C) 2009 Peter Soetens
8  email : peter@thesourcworks.com
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 
40 #ifdef ORO_PRAGMA_INTERFACE
41 #pragma implementation
42 #endif
43 #include "Time.hpp"
44 #include "Activity.hpp"
45 #include "os/MutexLock.hpp"
46 #include "os/traces.h"
47 #include "Logger.hpp"
48 #include "rtt-fwd.hpp"
50 
51 #include <cmath>
52 
53 namespace RTT
54 {
55  using namespace detail;
56 
57  Activity::Activity(RunnableInterface* _r, const std::string& name )
58  : ActivityInterface(_r), os::Thread(ORO_SCHED_OTHER, RTT::os::LowestPriority, 0.0, 0, name ),
59  update_period(0.0), mtimeout(false), mstopRequested(false), mwaitpolicy(ORO_WAIT_ABS)
60  {
61  }
62 
63  Activity::Activity(int priority, RunnableInterface* r, const std::string& name )
64  : ActivityInterface(r), os::Thread(ORO_SCHED_RT, priority, 0.0, 0, name ),
66  {
67  }
68 
69  Activity::Activity(int priority, Seconds period, RunnableInterface* r, const std::string& name )
70  : ActivityInterface(r), os::Thread(ORO_SCHED_RT, priority, period, 0, name ),
72  {
73  // We pass the requested period to the constructor to not confuse users with log messages.
74  // Then we clear it immediately again in order to force the Thread implementation to
75  // non periodic:
76  Thread::setPeriod(0,0);
77  }
78 
79  Activity::Activity(int scheduler, int priority, RunnableInterface* r, const std::string& name )
80  : ActivityInterface(r), os::Thread(scheduler, priority, 0.0, 0, name ),
82  {
83  }
84 
85  Activity::Activity(int scheduler, int priority, Seconds period, RunnableInterface* r, const std::string& name )
86  : ActivityInterface(r), os::Thread(scheduler, priority, period, 0, name ),
88  {
89  // We pass the requested period to the constructor to not confuse users with log messages.
90  // Then we clear it immediately again in order to force the Thread implementation to
91  // non periodic:
92  Thread::setPeriod(0,0);
93  }
94 
95  Activity::Activity(int scheduler, int priority, Seconds period, unsigned cpu_affinity, RunnableInterface* r, const std::string& name )
96  : ActivityInterface(r), os::Thread(scheduler, priority, period, cpu_affinity, name ),
98  {
99  // We pass the requested period to the constructor to not confuse users with log messages.
100  // Then we clear it immediately again in order to force the Thread implementation to
101  // non periodic:
102  Thread::setPeriod(0,0);
103  }
104 
106  {
107  stop();
108 
109  // We need to join the activity's thread before destruction as the thread function might still
110  // access member variables. Activity::stop() does not guarantuee to stop the underlying thread.
111  terminate();
112  }
113 
115  return this;
116  }
117 
119  if ( runner )
120  return runner->initialize();
121  return true;
122  }
123 
124  void Activity::step() {
125  if ( runner )
126  runner->step();
127  }
128 
130  if ( runner )
131  runner->work(reason);
132  }
133 
135  if (s < 0.0)
136  return false;
137  update_period = s;
138  // we need to trigger internally to get the period started
139  trigger();
140  return true;
141  }
142 
144  return update_period;
145  }
146 
148  tracepoint(orocos_rtt, Activity_trigger, getName());
149  if ( ! Thread::isActive() )
150  return false;
151  //a trigger is always allowed when active
153  Thread::start();
154  return true;
155  }
156 
158  // only allowed in slaves
159  return false;
160  }
161 
163  // a user-timeout is only allowed for non-periodics
164  if ( update_period > 0) {
165  return false;
166  }
167  mtimeout = true;
169  Thread::start();
170  return true;
171  }
172 
173  void Activity::loop() {
174  nsecs wakeup = 0;
175  int overruns = 0;
176  while ( true ) {
177  // since update_period may be changed at any time, we need to recheck it each time:
178  if ( update_period > 0.0) {
179  // initialize first wakeup time if we are periodic.
180  if ( wakeup == 0 ) {
182  }
183  } else {
184  // only clear if update_period <= 0.0 :
185  wakeup = 0;
186  }
187 
188  // periodic: we flag mtimeout below; non-periodic: we flag mtimeout in timeout()
189  if (mtimeout) {
190  // was a timeout() call, or internally generated after wakeup
191  mtimeout = false;
192  this->step();
194  } else {
195  // was a trigger() call
196  if ( update_period > 0 ) {
197  this->step();
199  } else {
200  if (runner) {
201  runner->loop();
203  } else {
204  this->step();
206  }
207  }
208  // if a timeout() was done during work(), we will re-enter
209  // loop() due to the Thread::start().
210  }
211  // next, sleep/wait
212  os::MutexLock lock(msg_lock);
213  if ( wakeup == 0 ) {
214  // non periodic, default behavior:
215  return;
216  } else {
217  // If periodic, sleep until wakeup time or a message comes in.
218  // when wakeup time passed, wait_until will return false and we recalculate wakeup + update_period
219  bool time_elapsed = ! msg_cond.wait_until(msg_lock,wakeup);
220 
221  if (time_elapsed) {
223 
224  // calculate next wakeup point
226  wakeup = wakeup + nsperiod;
227 
228  // detect overruns
229  if ( wakeup < now )
230  {
231  ++overruns;
232  if (overruns == maxOverRun)
233  break; // break while(true)
234  }
235  else if (overruns != 0) {
236  --overruns;
237  }
238 
239  // ORO_WAIT_REL: reset next wakeup time to now (before step) + period
240  if ( mwaitpolicy == ORO_WAIT_REL ) {
241  wakeup = now + nsperiod;
242  }
243  mtimeout = true;
244  }
245  }
246  if (mstopRequested) {
247  mstopRequested = false; // guarded by Mutex lock
248  return;
249  }
250  }
251  if (overruns == maxOverRun)
252  {
253  this->emergencyStop();
255  << " got too many periodic overruns in step() ("
256  << overruns << " times), stopped Thread !"
257  << endlog();
258  log(Critical) << " See Thread::setMaxOverrun() for info."
259  << endlog();
260  }
261  }
262 
264  if ( runner )
265  return runner->breakLoop();
266  return false;
267  }
268 
270  if ( runner )
271  runner->finalize();
272  }
273 
274 
276  mstopRequested = false;
277  return Thread::start();
278  }
279 
281  {
282  if (!active)
283  return false;
284 
285  running = false;
286 
287  // first of all, exit loop() if possible:
288  {
289  os::MutexLock lock(msg_lock); // protects stopRequested
290  mstopRequested = true;
292  }
293 
294  if (update_period == 0)
295  {
296  if ( inloop ) {
297  if ( !this->breakLoop() ) {
298  log(Warning) << "Failed to stop thread " << this->getName() << ": breakLoop() returned false."<<endlog();
299  running = true;
300  return false;
301  }
302  // breakLoop was ok, wait for loop() to return.
303  }
305  if ( !lock.isSuccessful() ) {
306  log(Error) << "Failed to stop thread " << this->getName() << ": breakLoop() returned true, but loop() function did not return after "<<getStopTimeout() << " second(s)."<<endlog();
307  running = true;
308  return false;
309  }
310  } else {
311  //
313  if ( lock.isSuccessful() ) {
314  // drop out of periodic mode.
316  } else {
317  log(Error) << "Failed to stop thread " << this->getName() << ": step() function did not return after "<< getStopTimeout() <<" second(s)."<<endlog();
318  running = true;
319  return false;
320  }
321  }
322 
323  this->finalize();
324  active = false;
325  return true;
326  }
327 
328  bool Activity::isRunning() const {
329  return Thread::isRunning();
330  }
331 
332  bool Activity::isActive() const {
333  return Thread::isActive();
334  }
335 
336  bool Activity::isPeriodic() const {
337  return Thread::isPeriodic() || (update_period != 0.0);
338  }
339 
340  unsigned Activity::getCpuAffinity() const
341  {
342  return Thread::getCpuAffinity();
343  }
344 
345  bool Activity::setCpuAffinity(unsigned cpu)
346  {
347  return Thread::setCpuAffinity(cpu);
348  }
349 
351  {
352  mwaitpolicy = p;
353  }
354 
355 }
virtual void work(WorkReason reason)
virtual bool isPeriodic() const
Definition: Activity.cpp:336
double update_period
Definition: Activity.hpp:228
INTERNAL_QUAL void rtos_task_make_periodic(RTOS_TASK *mytask, NANO_TIME nanosecs)
double Seconds
Definition: os/Time.hpp:53
virtual void work(base::RunnableInterface::WorkReason reason)
Definition: Activity.cpp:129
#define ORO_WAIT_ABS
Definition: ecos/fosi.h:64
virtual bool stop()
Definition: Activity.cpp:280
nsecs getNSecs() const
virtual os::ThreadInterface * thread()
Definition: Activity.cpp:114
virtual void finalize()
Definition: Activity.cpp:269
virtual void step()
Definition: Activity.cpp:124
virtual void loop()
Definition: Activity.cpp:173
A class for running a certain piece of code in a thread.
#define tracepoint(provider, tracepoint,...)
Definition: traces.h:9
void emergencyStop()
Definition: Thread.cpp:235
MutexRecursive breaker
Definition: Thread.hpp:341
virtual bool setCpuAffinity(unsigned cpu_affinity)
Definition: Thread.cpp:608
bool mstopRequested
Definition: Activity.hpp:234
static TimeService * Instance()
Definition: TimeService.cpp:60
void setWaitPeriodPolicy(int p)
Definition: Activity.cpp:350
virtual bool initialize()
Definition: Activity.cpp:118
virtual RTOS_TASK * getTask()
Definition: Thread.hpp:205
virtual bool breakLoop()
Definition: Activity.cpp:263
virtual bool execute()
Definition: Activity.cpp:157
virtual bool isActive() const
Definition: Thread.cpp:471
Interface to start/stop and query a Activity.
virtual bool timeout()
Definition: Activity.cpp:162
bool wait_until(Mutex &m, nsecs abs_time)
Definition: Condition.hpp:129
virtual bool start()
Definition: Activity.cpp:275
const char * rtos_task_get_name(const RTOS_TASK *task)
A MutexTimedLock locks a Mutex object on construction and if successful, unlocks it on destruction of...
Definition: MutexLock.hpp:146
virtual unsigned getCpuAffinity() const
Definition: Thread.cpp:613
os::Condition msg_cond
Definition: Activity.hpp:224
virtual bool trigger()
Definition: Activity.cpp:147
void terminate()
Definition: Thread.cpp:628
RTOS_TASK rtos_task
Definition: Thread.hpp:331
bool setPeriod(Seconds s)
Definition: Thread.cpp:543
nsecs Seconds_to_nsecs(const Seconds s)
Definition: os/Time.hpp:107
virtual Seconds getPeriod() const
Definition: Activity.cpp:143
virtual bool setPeriod(Seconds period)
Definition: Activity.cpp:134
virtual bool initialize()=0
virtual bool start()
Definition: Thread.cpp:345
#define ORO_WAIT_REL
Definition: ecos/fosi.h:65
const int LowestPriority
Definition: ecosthreads.cpp:44
#define ORO_SCHED_RT
Definition: ecos/fosi.h:61
Seconds getStopTimeout() const
Definition: Thread.cpp:415
NANO_TIME period
Definition: Thread.hpp:352
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:53
virtual bool isActive() const
Definition: Activity.cpp:332
os::Mutex msg_lock
Definition: Activity.hpp:223
long long nsecs
Definition: os/Time.hpp:69
virtual ~Activity()
Definition: Activity.cpp:105
static Logger & log()
Definition: Logger.hpp:350
#define ORO_SCHED_OTHER
Definition: ecos/fosi.h:62
virtual bool isPeriodic() const
Definition: Thread.cpp:588
static Logger::LogFunction endlog()
Definition: Logger.hpp:362
virtual bool isRunning() const
Definition: Activity.cpp:328
virtual const char * getName() const
Definition: Thread.cpp:645
virtual bool setCpuAffinity(unsigned cpu)
Definition: Activity.cpp:345
virtual bool isRunning() const
Definition: Thread.cpp:466
MutexLock is a scope based Monitor, protecting critical sections with a Mutex object through locking ...
Definition: MutexLock.hpp:51
Activity(base::RunnableInterface *r=0, const std::string &name="Activity")
Create a not real-time Activity. This creates a not real-time, non-periodic thread, with priority equal to RTT::os::LowestPriority.
Definition: Activity.cpp:57
virtual unsigned getCpuAffinity() const
Definition: Activity.cpp:340


rtt
Author(s): RTT Developers
autogenerated on Fri Oct 25 2019 03:59:30