YARP
Yet Another Robot Platform
PeriodicThread.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * Copyright (C) 2006-2010 RobotCub Consortium
4  * All rights reserved.
5  *
6  * This software may be modified and distributed under the terms of the
7  * BSD-3-Clause license. See the accompanying LICENSE file for details.
8  */
9 
10 #include <yarp/os/PeriodicThread.h>
11 
12 #include <yarp/os/SystemClock.h>
15 
16 #include <cmath>
17 #include <mutex>
18 
19 using namespace yarp::os::impl;
20 using namespace yarp::os;
21 
22 
24 {
25 private:
26  double adaptedPeriod;
27  PeriodicThread* owner;
28  mutable std::mutex mutex;
29 
30  double elapsed;
31  double sleepPeriod;
32 
33  bool suspended;
34  double totalUsed; //total time taken iterations
35  unsigned int count; //number of iterations from last reset
36  unsigned int estPIt; //number of useful iterations for period estimation
37  double totalT; //time bw run, accumulated
38  double sumTSq; //cumulative sum sq of estimated period dT
39  double sumUsedSq; //cumulative sum sq of estimated thread tun
40  double previousRun; //time when last iteration started
41  double currentRun; //time when this iteration started
42  bool scheduleReset;
43 
44  using NowFuncPtr = double (*)();
45  using DelayFuncPtr = void (*)(double);
46  const NowFuncPtr nowFunc;
47  const DelayFuncPtr delayFunc;
48 
49  void _resetStat()
50  {
51  totalUsed = 0;
52  count = 0;
53  estPIt = 0;
54  totalT = 0;
55  sumUsedSq = 0;
56  sumTSq = 0;
57  elapsed = 0;
58  scheduleReset = false;
59  }
60 
61 public:
63  adaptedPeriod(p),
64  owner(owner),
65  elapsed(0),
66  sleepPeriod(adaptedPeriod),
67  suspended(false),
68  totalUsed(0),
69  count(0),
70  estPIt(0),
71  totalT(0),
72  sumTSq(0),
73  sumUsedSq(0),
74  previousRun(0),
75  currentRun(0),
76  scheduleReset(false),
77  nowFunc(useSystemClock == ShouldUseSystemClock::Yes ? SystemClock::nowSystem : yarp::os::Time::now),
78  delayFunc(useSystemClock == ShouldUseSystemClock::Yes ? SystemClock::delaySystem : yarp::os::Time::delay)
79  {
80  }
81 
82  void resetStat()
83  {
84  scheduleReset = true;
85  }
86 
87  double getEstimatedPeriod() const
88  {
89  double ret;
90  lock();
91  if (estPIt == 0) {
92  ret = 0;
93  } else {
94  ret = (totalT / estPIt);
95  }
96  unlock();
97  return ret;
98  }
99 
100  void getEstimatedPeriod(double& av, double& std) const
101  {
102  lock();
103  if (estPIt == 0) {
104  av = 0;
105  std = 0;
106  } else {
107  av = totalT / estPIt;
108  if (estPIt > 1) {
109  std = sqrt(((1.0 / (estPIt - 1)) * (sumTSq - estPIt * av * av)));
110  } else {
111  std = 0;
112  }
113  }
114  unlock();
115  }
116 
117  unsigned int getIterations() const
118  {
119  lock();
120  unsigned int ret = count;
121  unlock();
122  return ret;
123  }
124 
125  double getEstimatedUsed() const
126  {
127  double ret;
128  lock();
129  if (count < 1) {
130  ret = 0.0;
131  } else {
132  ret = totalUsed / count;
133  }
134  unlock();
135  return ret;
136  }
137 
138  void getEstimatedUsed(double& av, double& std) const
139  {
140  lock();
141  if (count < 1) {
142  av = 0;
143  std = 0;
144  } else {
145  av = totalUsed / count;
146  if (count > 1) {
147  std = sqrt((1.0 / (count - 1)) * (sumUsedSq - count * av * av));
148  } else {
149  std = 0;
150  }
151  }
152  unlock();
153  }
154 
155 
156  void step()
157  {
158  lock();
159  currentRun = nowFunc();
160 
161  if (scheduleReset) {
162  _resetStat();
163  }
164 
165  if (count > 0) {
166  double dT = (currentRun - previousRun);
167 
168  sumTSq += dT * dT;
169  totalT += dT;
170 
171  if (adaptedPeriod < 0) {
172  adaptedPeriod = 0;
173  }
174 
175  estPIt++;
176  }
177 
178  previousRun = currentRun;
179  unlock();
180 
181  if (!suspended) {
182  owner->run();
183  }
184 
185 
186  // At the end of each run of updateModule function, the thread is supposed
187  // to be suspended and release CPU to other threads.
188  // Calling a yield here will help the threads to alternate in the execution.
189  // Note: call yield BEFORE computing elapsed time, so that any time spent due to
190  // yield is took into account and the sleep time is correct.
191  yield();
192 
193  lock();
194  count++;
195  double elapsed = nowFunc() - currentRun;
196  //save last
197  totalUsed += elapsed;
198  sumUsedSq += elapsed * elapsed;
199  unlock();
200 
201  sleepPeriod = adaptedPeriod - elapsed; // everything is in [seconds] except period, for it is used in the interface as [ms]
202 
203  delayFunc(sleepPeriod);
204  }
205 
206  void run() override
207  {
208  while (!isClosing()) {
209  step();
210  }
211  }
212 
213  bool threadInit() override
214  {
215  return owner->threadInit();
216  }
217 
218  void threadRelease() override
219  {
220  owner->threadRelease();
221  }
222 
223  bool setPeriod(double period)
224  {
225  adaptedPeriod = period;
226  return true;
227  }
228 
229  double getPeriod() const
230  {
231  return adaptedPeriod;
232  }
233 
234  bool isSuspended() const
235  {
236  return suspended;
237  }
238 
239  void suspend()
240  {
241  suspended = true;
242  }
243 
244  void resume()
245  {
246  suspended = false;
247  }
248 
249  void afterStart(bool s) override
250  {
251  owner->afterStart(s);
252  }
253 
254  void beforeStart() override
255  {
256  owner->beforeStart();
257  }
258 
259  void lock() const
260  {
261  mutex.lock();
262  }
263 
264  void unlock() const
265  {
266  mutex.unlock();
267  }
268 };
269 
270 
272  mPriv(new Private(this, period, useSystemClock))
273 {
274 }
275 
277 {
278  delete mPriv;
279 }
280 
281 bool PeriodicThread::setPeriod(double period)
282 {
283  return mPriv->setPeriod(period);
284 }
285 
287 {
288  return mPriv->getPeriod();
289 }
290 
292 {
293  return mPriv->isSuspended();
294 }
295 
297 {
298  mPriv->close();
299 }
300 
302 {
303  mPriv->askToClose();
304 }
305 
307 {
308  mPriv->step();
309 }
310 
312 {
313  return mPriv->start();
314 }
315 
317 {
318  return mPriv->isRunning();
319 }
320 
322 {
323  mPriv->suspend();
324 }
325 
327 {
328  mPriv->resume();
329 }
330 
331 unsigned int PeriodicThread::getIterations() const
332 {
333  return mPriv->getIterations();
334 }
335 
337 {
338  return mPriv->getEstimatedPeriod();
339 }
340 
342 {
343  return mPriv->getEstimatedUsed();
344 }
345 
346 void PeriodicThread::getEstimatedPeriod(double& av, double& std) const
347 {
348  mPriv->getEstimatedPeriod(av, std);
349 }
350 
351 void PeriodicThread::getEstimatedUsed(double& av, double& std) const
352 {
353  mPriv->getEstimatedUsed(av, std);
354 }
355 
357 {
358  mPriv->resetStat();
359 }
360 
362 {
363  return true;
364 }
365 
367 {
368 }
369 
371 {
372 }
373 
374 void PeriodicThread::afterStart(bool success)
375 {
376  YARP_UNUSED(success);
377 }
378 
379 int PeriodicThread::setPriority(int priority, int policy)
380 {
381  return mPriv->setPriority(priority, policy);
382 }
383 
385 {
386  return mPriv->getPriority();
387 }
388 
390 {
391  return mPriv->getPolicy();
392 }
yarp::os::PeriodicThread::Private::threadRelease
void threadRelease() override
Definition: PeriodicThread.cpp:218
std_msgs::Time
yarp::rosmsg::std_msgs::Time Time
Definition: Time.h:24
yarp::os::PeriodicThread::Private::getIterations
unsigned int getIterations() const
Definition: PeriodicThread.cpp:117
SystemClock.h
yarp::os::ShouldUseSystemClock::No
@ No
yarp::os::PeriodicThread::resume
void resume()
Resume the thread if previously suspended.
Definition: PeriodicThread.cpp:326
yarp::os::PeriodicThread::Private::suspend
void suspend()
Definition: PeriodicThread.cpp:239
yarp::os::PeriodicThread::getPolicy
int getPolicy() const
Query the current scheduling policy of the thread, if the OS supports that.
Definition: PeriodicThread.cpp:389
ThreadImpl.h
yarp::os::PeriodicThread::getPriority
int getPriority() const
Query the current priority of the thread, if the OS supports that.
Definition: PeriodicThread.cpp:384
yarp::os::PeriodicThread::Private::afterStart
void afterStart(bool s) override
Definition: PeriodicThread.cpp:249
yarp::os::PeriodicThread::Private::run
void run() override
Definition: PeriodicThread.cpp:206
yarp::os::PeriodicThread::Private::step
void step()
Definition: PeriodicThread.cpp:156
yarp::os::PeriodicThread::Private::threadInit
bool threadInit() override
Definition: PeriodicThread.cpp:213
yarp::os::PeriodicThread::getEstimatedUsed
double getEstimatedUsed() const
Return the estimated duration of the run() function since last reset.
Definition: PeriodicThread.cpp:341
yarp::os::PeriodicThread::PeriodicThread
PeriodicThread(double period, ShouldUseSystemClock useSystemClock=ShouldUseSystemClock::No)
Constructor.
Definition: PeriodicThread.cpp:271
yarp::os::PeriodicThread::getPeriod
double getPeriod() const
Return the current period of the thread.
Definition: PeriodicThread.cpp:286
YARP_UNUSED
#define YARP_UNUSED(var)
Definition: api.h:159
ret
bool ret
Definition: ImplementAxisInfo.cpp:72
yarp::os::PeriodicThread::beforeStart
virtual void beforeStart()
Called just before a new thread starts.
Definition: PeriodicThread.cpp:370
yarp::os::PeriodicThread::Private::getEstimatedPeriod
void getEstimatedPeriod(double &av, double &std) const
Definition: PeriodicThread.cpp:100
yarp::os::PeriodicThread::isRunning
bool isRunning() const
Returns true when the thread is started, false otherwise.
Definition: PeriodicThread.cpp:316
yarp::os::Time::now
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:124
yarp::os::PeriodicThread::getEstimatedPeriod
double getEstimatedPeriod() const
Return estimated period since last reset.
Definition: PeriodicThread.cpp:336
yarp::os::PeriodicThread::Private::setPeriod
bool setPeriod(double period)
Definition: PeriodicThread.cpp:223
yarp::os::PeriodicThread::Private::getEstimatedPeriod
double getEstimatedPeriod() const
Definition: PeriodicThread.cpp:87
yarp::os::PeriodicThread::Private::beforeStart
void beforeStart() override
Definition: PeriodicThread.cpp:254
yarp::os::Time::useSystemClock
void useSystemClock()
Configure YARP to use system time (this is the default).
Definition: Time.cpp:147
yarp::os::SystemClock
Definition: SystemClock.h:18
yarp::os::PeriodicThread::Private::resetStat
void resetStat()
Definition: PeriodicThread.cpp:82
yarp::os::PeriodicThread::afterStart
virtual void afterStart(bool success)
Called just after a new thread starts (or fails to start), this is executed by the same thread that c...
Definition: PeriodicThread.cpp:374
yarp::os::PeriodicThread::resetStat
void resetStat()
Reset thread statistics.
Definition: PeriodicThread.cpp:356
yarp::os::PeriodicThread::start
bool start()
Call this to start the thread.
Definition: PeriodicThread.cpp:311
yarp::os::Time::yield
void yield()
The calling thread releases its remaining quantum upon calling this function.
Definition: Time.cpp:141
yarp::os::PeriodicThread::setPeriod
bool setPeriod(double period)
Set the (new) period of the thread.
Definition: PeriodicThread.cpp:281
yarp::os::PeriodicThread::Private::getEstimatedUsed
double getEstimatedUsed() const
Definition: PeriodicThread.cpp:125
yarp::os::PeriodicThread::suspend
void suspend()
Suspend the thread, the thread keeps running by doLoop is never executed.
Definition: PeriodicThread.cpp:321
yarp::os::PeriodicThread
An abstraction for a periodic thread.
Definition: PeriodicThread.h:25
yarp::os::PeriodicThread::Private::isSuspended
bool isSuspended() const
Definition: PeriodicThread.cpp:234
yarp::os::PeriodicThread::~PeriodicThread
virtual ~PeriodicThread()
Definition: PeriodicThread.cpp:276
PeriodicThread.h
yarp::os::PeriodicThread::setPriority
int setPriority(int priority, int policy=-1)
Set the priority and scheduling policy of the thread, if the OS supports that.
Definition: PeriodicThread.cpp:379
yarp::os::PeriodicThread::Private::getEstimatedUsed
void getEstimatedUsed(double &av, double &std) const
Definition: PeriodicThread.cpp:138
yarp::os::PeriodicThread::Private::resume
void resume()
Definition: PeriodicThread.cpp:244
yarp::os::PeriodicThread::askToStop
void askToStop()
Stop the thread.
Definition: PeriodicThread.cpp:301
yarp::os::impl::ThreadImpl
An abstraction for a thread of execution.
Definition: ThreadImpl.h:26
yarp::os
An interface to the operating system, including Port based communication.
Definition: AbstractCarrier.h:17
yarp::os::PeriodicThread::threadInit
virtual bool threadInit()
Initialization method.
Definition: PeriodicThread.cpp:361
yarp::os::PeriodicThread::Private
Definition: PeriodicThread.cpp:24
yarp
The main, catch-all namespace for YARP.
Definition: environment.h:18
yarp::os::ShouldUseSystemClock
ShouldUseSystemClock
Definition: Time.h:23
yarp::os::PeriodicThread::getIterations
unsigned int getIterations() const
Return the number of iterations performed since last reset.
Definition: PeriodicThread.cpp:331
yarp::os::PeriodicThread::isSuspended
bool isSuspended() const
Returns true when the thread is suspended, false otherwise.
Definition: PeriodicThread.cpp:291
yarp::os::PeriodicThread::Private::lock
void lock() const
Definition: PeriodicThread.cpp:259
yarp::os::PeriodicThread::stop
void stop()
Call this to stop the thread, this call blocks until the thread is terminated (and releaseThread() ca...
Definition: PeriodicThread.cpp:296
yarp::os::PeriodicThread::Private::getPeriod
double getPeriod() const
Definition: PeriodicThread.cpp:229
yarp::os::PeriodicThread::run
virtual void run()=0
Loop function.
yarp::os::PeriodicThread::step
void step()
Call this to "step" the thread rather than starting it.
Definition: PeriodicThread.cpp:306
yarp::os::PeriodicThread::threadRelease
virtual void threadRelease()
Release method.
Definition: PeriodicThread.cpp:366
PlatformTime.h
yarp::os::impl
The components from which ports and connections are built.
yarp::os::PeriodicThread::Private::Private
Private(PeriodicThread *owner, double p, ShouldUseSystemClock useSystemClock)
Definition: PeriodicThread.cpp:62
yarp::os::Time::delay
void delay(double seconds)
Wait for a certain number of seconds.
Definition: Time.cpp:114
yarp::os::PeriodicThread::Private::unlock
void unlock() const
Definition: PeriodicThread.cpp:264