Orocos Real-Time Toolkit  2.9.0
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 "Logger.hpp"
47 #include "rtt-fwd.hpp"
49 
50 #include <cmath>
51 
52 namespace RTT
53 {
54  using namespace detail;
55 
56  Activity::Activity(RunnableInterface* _r, const std::string& name )
57  : ActivityInterface(_r), os::Thread(ORO_SCHED_OTHER, RTT::os::LowestPriority, 0.0, 0, name ),
58  update_period(0.0), mtimeout(false), mstopRequested(false), mwaitpolicy(ORO_WAIT_ABS)
59  {
60  }
61 
62  Activity::Activity(int priority, RunnableInterface* r, const std::string& name )
63  : ActivityInterface(r), os::Thread(ORO_SCHED_RT, priority, 0.0, 0, name ),
65  {
66  }
67 
68  Activity::Activity(int priority, Seconds period, RunnableInterface* r, const std::string& name )
69  : ActivityInterface(r), os::Thread(ORO_SCHED_RT, priority, period, 0, name ),
71  {
72  // We pass the requested period to the constructor to not confuse users with log messages.
73  // Then we clear it immediately again in order to force the Thread implementation to
74  // non periodic:
75  Thread::setPeriod(0,0);
76  }
77 
78  Activity::Activity(int scheduler, int priority, RunnableInterface* r, const std::string& name )
79  : ActivityInterface(r), os::Thread(scheduler, priority, 0.0, 0, name ),
81  {
82  }
83 
84  Activity::Activity(int scheduler, int priority, Seconds period, RunnableInterface* r, const std::string& name )
85  : ActivityInterface(r), os::Thread(scheduler, priority, period, 0, name ),
87  {
88  // We pass the requested period to the constructor to not confuse users with log messages.
89  // Then we clear it immediately again in order to force the Thread implementation to
90  // non periodic:
91  Thread::setPeriod(0,0);
92  }
93 
94  Activity::Activity(int scheduler, int priority, Seconds period, unsigned cpu_affinity, RunnableInterface* r, const std::string& name )
95  : ActivityInterface(r), os::Thread(scheduler, priority, period, cpu_affinity, name ),
97  {
98  // We pass the requested period to the constructor to not confuse users with log messages.
99  // Then we clear it immediately again in order to force the Thread implementation to
100  // non periodic:
101  Thread::setPeriod(0,0);
102  }
103 
105  {
106  stop();
107 
108  // We need to join the activity's thread before destruction as the thread function might still
109  // access member variables. Activity::stop() does not guarantuee to stop the underlying thread.
110  terminate();
111  }
112 
114  return this;
115  }
116 
118  if ( runner )
119  return runner->initialize();
120  return true;
121  }
122 
123  void Activity::step() {
124  if ( runner )
125  runner->step();
126  }
127 
129  if ( runner )
130  runner->work(reason);
131  }
132 
134  if (s < 0.0)
135  return false;
136  update_period = s;
137  // we need to trigger internally to get the period started
138  trigger();
139  return true;
140  }
141 
143  return update_period;
144  }
145 
147  if ( ! Thread::isActive() )
148  return false;
149  //a trigger is always allowed when active
151  Thread::start();
152  return true;
153  }
154 
156  // only allowed in slaves
157  return false;
158  }
159 
161  // a user-timeout is only allowed for non-periodics
162  if ( update_period > 0) {
163  return false;
164  }
165  mtimeout = true;
167  Thread::start();
168  return true;
169  }
170 
171  void Activity::loop() {
172  nsecs wakeup = 0;
173  int overruns = 0;
174  while ( true ) {
175  // since update_period may be changed at any time, we need to recheck it each time:
176  if ( update_period > 0.0) {
177  // initialize first wakeup time if we are periodic.
178  if ( wakeup == 0 ) {
180  }
181  } else {
182  // only clear if update_period <= 0.0 :
183  wakeup = 0;
184  }
185 
186  // periodic: we flag mtimeout below; non-periodic: we flag mtimeout in timeout()
187  if (mtimeout) {
188  // was a timeout() call, or internally generated after wakeup
189  mtimeout = false;
190  this->step();
192  } else {
193  // was a trigger() call
194  if ( update_period > 0 ) {
195  this->step();
197  } else {
198  if (runner) {
199  runner->loop();
201  } else {
202  this->step();
204  }
205  }
206  // if a timeout() was done during work(), we will re-enter
207  // loop() due to the Thread::start().
208  }
209  // next, sleep/wait
210  os::MutexLock lock(msg_lock);
211  if ( wakeup == 0 ) {
212  // non periodic, default behavior:
213  return;
214  } else {
215  // If periodic, sleep until wakeup time or a message comes in.
216  // when wakeup time passed, wait_until will return false and we recalculate wakeup + update_period
217  bool time_elapsed = ! msg_cond.wait_until(msg_lock,wakeup);
218 
219  if (time_elapsed) {
221 
222  // calculate next wakeup point
224  wakeup = wakeup + nsperiod;
225 
226  // detect overruns
227  if ( wakeup < now )
228  {
229  ++overruns;
230  if (overruns == maxOverRun)
231  break; // break while(true)
232  }
233  else if (overruns != 0) {
234  --overruns;
235  }
236 
237  // ORO_WAIT_REL: reset next wakeup time to now (before step) + period
238  if ( mwaitpolicy == ORO_WAIT_REL ) {
239  wakeup = now + nsperiod;
240  }
241  mtimeout = true;
242  }
243  }
244  if (mstopRequested) {
245  mstopRequested = false; // guarded by Mutex lock
246  return;
247  }
248  }
249  if (overruns == maxOverRun)
250  {
251  this->emergencyStop();
252  log(Critical) << rtos_task_get_name(this->getTask())
253  << " got too many periodic overruns in step() ("
254  << overruns << " times), stopped Thread !"
255  << endlog();
256  log(Critical) << " See Thread::setMaxOverrun() for info."
257  << endlog();
258  }
259  }
260 
262  if ( runner )
263  return runner->breakLoop();
264  return false;
265  }
266 
268  if ( runner )
269  runner->finalize();
270  }
271 
272 
274  mstopRequested = false;
275  return Thread::start();
276  }
277 
279  {
280  if (!active)
281  return false;
282 
283  running = false;
284 
285  // first of all, exit loop() if possible:
286  {
287  os::MutexLock lock(msg_lock); // protects stopRequested
288  mstopRequested = true;
290  }
291 
292  if (update_period == 0)
293  {
294  if ( inloop ) {
295  if ( !this->breakLoop() ) {
296  log(Warning) << "Failed to stop thread " << this->getName() << ": breakLoop() returned false."<<endlog();
297  running = true;
298  return false;
299  }
300  // breakLoop was ok, wait for loop() to return.
301  }
303  if ( !lock.isSuccessful() ) {
304  log(Error) << "Failed to stop thread " << this->getName() << ": breakLoop() returned true, but loop() function did not return after "<<getStopTimeout() << " second(s)."<<endlog();
305  running = true;
306  return false;
307  }
308  } else {
309  //
311  if ( lock.isSuccessful() ) {
312  // drop out of periodic mode.
314  } else {
315  log(Error) << "Failed to stop thread " << this->getName() << ": step() function did not return after "<< getStopTimeout() <<" second(s)."<<endlog();
316  running = true;
317  return false;
318  }
319  }
320 
321  this->finalize();
322  active = false;
323  return true;
324  }
325 
326  bool Activity::isRunning() const {
327  return Thread::isRunning();
328  }
329 
330  bool Activity::isActive() const {
331  return Thread::isActive();
332  }
333 
334  bool Activity::isPeriodic() const {
335  return Thread::isPeriodic() || (update_period != 0.0);
336  }
337 
338  unsigned Activity::getCpuAffinity() const
339  {
340  return Thread::getCpuAffinity();
341  }
342 
343  bool Activity::setCpuAffinity(unsigned cpu)
344  {
345  return Thread::setCpuAffinity(cpu);
346  }
347 
349  {
350  mwaitpolicy = p;
351  }
352 
353 }
virtual void loop()
Definition: Activity.cpp:171
double update_period
The period at which the Activity steps().
Definition: Activity.hpp:228
virtual bool stop()
Stop the activity This will stop the activity by removing it from the &#39;run-queue&#39; of a thread or call...
Definition: Activity.cpp:278
INTERNAL_QUAL void rtos_task_make_periodic(RTOS_TASK *mytask, NANO_TIME nanosecs)
This function is to inform the RTOS that a thread is switching between periodic or non-periodic execu...
double Seconds
Seconds are stored as a double precision float.
Definition: Time.hpp:53
virtual Seconds getPeriod() const
Get the periodicity of this activity in Seconds.
Definition: Activity.cpp:142
virtual bool isPeriodic() const
Inspect if this activity is periodic.
Definition: Activity.cpp:334
virtual bool initialize()
Definition: Activity.cpp:117
A Thread object executes user code in its own thread.
Definition: Thread.hpp:109
virtual void finalize()
Definition: Activity.cpp:267
#define ORO_WAIT_ABS
Definition: fosi.h:52
virtual void work(base::RunnableInterface::WorkReason reason)
Definition: Activity.cpp:128
nsecs getNSecs() const
Get current nsecs of the System clock.
Activity(base::RunnableInterface *r=0, const std::string &name="Activity")
Create a not real-time Activity.
Definition: Activity.cpp:56
A class for running a certain piece of code in a thread.
bool inloop
Is true when in the loop (isRunning() )
Definition: Thread.hpp:321
void emergencyStop()
Definition: Thread.cpp:226
MutexRecursive breaker
Used to implement synchronising breakLoop().
Definition: Thread.hpp:341
virtual bool setCpuAffinity(unsigned cpu_affinity)
Set cpu affinity for this thread.
Definition: Thread.cpp:601
bool mstopRequested
Definition: Activity.hpp:234
static TimeService * Instance()
Definition: TimeService.cpp:41
virtual void step()=0
The method that will be (periodically) executed when this object is run in an Activity.
void setWaitPeriodPolicy(int p)
Set the wait policy of a periodic thread.
Definition: Activity.cpp:348
virtual bool setPeriod(Seconds period)
Set the periodicity of this activity in Seconds.
Definition: Activity.cpp:133
virtual unsigned getCpuAffinity() const
Get the cpu affinity of this activity.
Definition: Activity.cpp:338
virtual RTOS_TASK * getTask()
Get the RTOS_TASK pointer.
Definition: Thread.hpp:205
bool running
Indicates if step() or loop() should be executed.
Definition: Thread.hpp:326
A thread which is being run.
This file has all the (periodic) thread specific interfaces.
virtual bool breakLoop()
Definition: Activity.cpp:261
virtual void step()
Definition: Activity.cpp:123
virtual bool isActive() const
Returns whether the thread is active.
Definition: Thread.cpp:464
Interface to start/stop and query a Activity.
virtual bool execute()
Execute this activity such that it executes a step or loop of the RunnableInterface.
Definition: Activity.cpp:155
bool wait_until(Mutex &m, nsecs abs_time)
Wait for this condition, but don&#39;t wait longer for it than the specified absolute time...
Definition: Condition.hpp:129
const char * rtos_task_get_name(const RTOS_TASK *task)
Returns the name by which a task is known in the RTOS.
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:606
int maxOverRun
The maximum times a periodic overrun may happen, or -1 if unlimited.
Definition: Thread.hpp:347
virtual bool timeout()
Requests this Activity to wakeup and call step() + work(Timeout).
Definition: Activity.cpp:160
virtual bool isRunning() const
Query if the activity is initialized and executing.
Definition: Activity.cpp:326
os::Condition msg_cond
Definition: Activity.hpp:224
bool isSuccessful()
Return if the locking of the Mutex was succesfull.
Definition: MutexLock.hpp:168
void terminate()
Exit and destroy the thread.
Definition: Thread.cpp:621
virtual void finalize()=0
The method that will be called after the last periodical execution of step() ( or non periodical exec...
bool active
When set to 1, the thread will run, when set to 0 the thread will stop ( isActive() ) ...
Definition: Thread.hpp:311
RTOS_TASK rtos_task
The realtime task structure created by this object.
Definition: Thread.hpp:331
virtual ~Activity()
Stops and terminates a Activity.
Definition: Activity.cpp:104
bool setPeriod(Seconds s)
Set the periodicity in Seconds.
Definition: Thread.cpp:536
virtual void loop()
The method that will be executed once when this class is run in a non periodic Activity.
nsecs Seconds_to_nsecs(const Seconds s)
Definition: Time.hpp:107
virtual bool initialize()=0
The method that will be called before the first periodical execution of step() ( or non periodical ex...
virtual bool start()
Start the Thread.
Definition: Thread.cpp:338
#define ORO_WAIT_REL
Definition: fosi.h:53
const int LowestPriority
An integer denoting the lowest priority of the selected OS.
Definition: ecosthreads.cpp:44
#define ORO_SCHED_RT
Definition: fosi.h:49
virtual bool breakLoop()
This method is called by the framework to break out of the loop() method.
Seconds getStopTimeout() const
Returns the desired timeout for stop(), in seconds.
Definition: Thread.cpp:408
NANO_TIME period
The period as it is passed to the operating system.
Definition: Thread.hpp:352
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
virtual bool start()
Start the activity.
Definition: Activity.cpp:273
virtual bool setCpuAffinity(unsigned cpu)
Set the cpu affinity of this activity.
Definition: Activity.cpp:343
os::Mutex msg_lock
Definition: Activity.hpp:223
virtual bool trigger()
Trigger that work has to be done.
Definition: Activity.cpp:146
long long nsecs
nanoseconds as a signed long long.
Definition: Time.hpp:69
bool mtimeout
When set to true, a next cycle will be a TimeOut cycle.
Definition: Activity.hpp:233
virtual os::ThreadInterface * thread()
Returns a pointer to the thread which will run this activity.
Definition: Activity.cpp:113
#define ORO_SCHED_OTHER
Definition: fosi.h:50
virtual bool isPeriodic() const
Definition: Thread.cpp:581
virtual void work(WorkReason reason)
Identical to step() but gives a reason why the function was called.
virtual const char * getName() const
Read the name of this task.
Definition: Thread.cpp:633
void broadcast()
Wake all threads that are blocking in wait() or wait_until().
Definition: Condition.hpp:113
virtual bool isRunning() const
Returns whether the thread is running.
Definition: Thread.cpp:459
MutexLock is a scope based Monitor, protecting critical sections with a Mutex object through locking ...
Definition: MutexLock.hpp:51
virtual bool isActive() const
Query if the activity is started.
Definition: Activity.cpp:330