Fawkes API  Fawkes Development Version
wait.cpp
1 
2 /***************************************************************************
3  * wait.cpp - TimeWait tool
4  *
5  * Created: Thu Nov 29 17:30:37 2007
6  * Copyright 2007 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <utils/time/clock.h>
25 #include <utils/time/time.h>
26 #include <utils/time/wait.h>
27 
28 #include <cstdlib>
29 #include <unistd.h>
30 
31 namespace fawkes {
32 
33 /** @class TimeWait <utils/time/wait.h>
34  * Time wait utility.
35  * This class allows for guaranteed waiting for a specified amout of time. It can
36  * either be used to suspend the current thread for at least the given time (static
37  * methods) or it can be used to reach a desired minimum loop time. For this instantiate
38  * the class and call mark_start() at the beginning of the loop and wait() at the end.
39  * wait() will then suspend the thread as long as needed to have the desired minimum
40  * loop time. The TimeWait utility will use the current clock time. Thus it may wait
41  * for a given amount of say simulated time.
42  * @author Tim Niemueller
43  */
44 
45 /** Constructor.
46  * @param clock clock to use
47  * @param desired_loop_time_usec desired minimum loop time in microseconds
48  */
49 TimeWait::TimeWait(Clock *clock, long int desired_loop_time_usec)
50 {
51  desired_loop_time_ = desired_loop_time_usec;
52  clock_ = clock;
53  until_ = new Time();
54  until_systime_ = new Time();
55  now_ = new Time();
56 }
57 
58 /** Destructor. */
60 {
61  delete until_;
62  delete until_systime_;
63  delete now_;
64 }
65 
66 /** Mark start of loop. */
67 void
69 {
70  clock_->get_time(until_);
71  *until_ += desired_loop_time_;
72  clock_->get_systime(until_systime_);
73  *until_systime_ += desired_loop_time_;
74 }
75 
76 /** Wait until minimum loop time has been reached. */
77 void
79 {
80  clock_->get_time(now_);
81  // we want to release run status at least shortly
82  usleep(0);
83 
84  long int remaining_usec = (*until_ - *now_).in_usec();
85  while (remaining_usec > 0) {
86  usleep(remaining_usec);
87  clock_->get_time(now_);
88  remaining_usec = (*until_ - *now_).in_usec();
89  }
90 }
91 
92 /** Wait until minimum loop time has been reached in real time.
93  * This uses the system time and not an external time source if defined.
94  */
95 void
97 {
98  clock_->get_systime(now_);
99  // we want to release run status at least shortly
100  usleep(0);
101 
102  long int remaining_usec = (*until_systime_ - *now_).in_usec();
103  while (remaining_usec > 0) {
104  usleep(remaining_usec);
105  clock_->get_systime(now_);
106  remaining_usec = (*until_systime_ - *now_).in_usec();
107  }
108 }
109 
110 /** Wait at least usec microseconds.
111  * Think of this as an uninterruptible usleep(). This method will not return before
112  * *at least* usec microseconds have passed. It may be longer but never less.
113  * Time is tracked in system time scale (real time).
114  * @param usec number of microseconds to wait at least
115  */
116 void
118 {
119  if (usec < 0)
120  return;
121  struct timeval start, now;
122  long int remaining_usec = usec;
123  gettimeofday(&start, NULL);
124  do {
125  usleep(remaining_usec);
126  gettimeofday(&now, NULL);
127  } while ((remaining_usec = usec - time_diff_usec(now, start)) > 0);
128 }
129 
130 /** Wait at least usec microseconds.
131  * Think of this as an uninterruptible usleep(). This method will not return before
132  * *at least* usec microseconds have passed. It may be longer but never less.
133  * Time is tracked in the current Clock time scale. This may be simulated time
134  * or real time. It is assumed that the (simulated time) is at worst slower, but never
135  * faster than real time. Thus 1 microsecond real time is at least 1 microsecond clock time.
136  * @param usec number of microseconds to wait at least
137  */
138 void
139 TimeWait::wait(long int usec)
140 {
141  if (usec < 0)
142  return;
143  Clock * clock = Clock::instance();
144  struct timeval start, now;
145  long int remaining_usec = usec;
146  clock->get_time(&start);
147  do {
148  usleep(remaining_usec);
149  clock->get_time(&now);
150  } while ((remaining_usec = usec - time_diff_usec(now, start)) > 0);
151 }
152 
153 } // end namespace fawkes
void wait()
Wait until minimum loop time has been reached.
Definition: wait.cpp:78
static Clock * instance()
Clock initializer.
Definition: clock.cpp:63
void get_time(struct timeval *tv) const
Returns the time of the selected time source.
Definition: clock.cpp:161
TimeWait(Clock *clock, long int desired_loop_time_usec)
Constructor.
Definition: wait.cpp:49
Fawkes library namespace.
void get_systime(struct timeval *tv) const
Returns the system time.
Definition: clock.cpp:215
This is supposed to be the central clock in Fawkes.
Definition: clock.h:34
A class for handling time.
Definition: time.h:92
void wait_systime()
Wait until minimum loop time has been reached in real time.
Definition: wait.cpp:96
long int time_diff_usec(const timeval &a, const timeval &b)
Get difference between two time structs in microseconds.
Definition: time.h:85
void mark_start()
Mark start of loop.
Definition: wait.cpp:68
~TimeWait()
Destructor.
Definition: wait.cpp:59