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/wait.h>
25 #include <utils/time/time.h>
26 #include <utils/time/clock.h>
27 
28 #include <unistd.h>
29 #include <cstdlib>
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 set_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 
59 /** Destructor. */
61 {
62  delete __until;
63  delete __until_systime;
64  delete __now;
65 }
66 
67 
68 /** Mark start of loop. */
69 void
71 {
72  __clock->get_time(__until);
73  *__until += __desired_loop_time;
74  __clock->get_systime(__until_systime);
75  *__until_systime += __desired_loop_time;
76 }
77 
78 
79 /** Wait until minimum loop time has been reached. */
80 void
82 {
83  __clock->get_time(__now);
84  // we want to release run status at least shortly
85  usleep(0);
86 
87  long int remaining_usec = (*__until - *__now).in_usec();
88  while ( remaining_usec > 0 ) {
89  usleep(remaining_usec);
90  __clock->get_time(__now);
91  remaining_usec = (*__until - *__now).in_usec();
92  }
93 }
94 
95 
96 /** Wait until minimum loop time has been reached in real time.
97  * This uses the system time and not an external time source if defined.
98  */
99 void
101 {
102  __clock->get_systime(__now);
103  // we want to release run status at least shortly
104  usleep(0);
105 
106  long int remaining_usec = (*__until_systime - *__now).in_usec();
107  while ( remaining_usec > 0 ) {
108  usleep(remaining_usec);
109  __clock->get_systime(__now);
110  remaining_usec = (*__until_systime - *__now).in_usec();
111  }
112 }
113 
114 
115 /** Wait at least usec microseconds.
116  * Think of this as an uninterruptible usleep(). This method will not return before
117  * *at least* usec microseconds have passed. It may be longer but never less.
118  * Time is tracked in system time scale (real time).
119  * @param usec number of microseconds to wait at least
120  */
121 void
123 {
124  if ( usec < 0 ) return;
125  struct timeval start, now;
126  long int remaining_usec = usec;
127  gettimeofday(&start, NULL);
128  do {
129  usleep(remaining_usec);
130  gettimeofday(&now, NULL);
131  } while ((remaining_usec = usec - time_diff_usec(now, start)) > 0);
132 }
133 
134 /** Wait at least usec microseconds.
135  * Think of this as an uninterruptible usleep(). This method will not return before
136  * *at least* usec microseconds have passed. It may be longer but never less.
137  * Time is tracked in the current Clock time scale. This may be simulated time
138  * or real time. It is assumed that the (simulated time) is at worst slower, but never
139  * faster than real time. Thus 1 microsecond real time is at least 1 microsecond clock time.
140  * @param usec number of microseconds to wait at least
141  */
142 void
143 TimeWait::wait(long int usec)
144 {
145  if ( usec < 0 ) return;
146  Clock *clock = Clock::instance();
147  struct timeval start, now;
148  long int remaining_usec = usec;
149  clock->get_time(&start);
150  do {
151  usleep(remaining_usec);
152  clock->get_time(&now);
153  } while ((remaining_usec = usec - time_diff_usec(now, start)) > 0);
154 }
155 
156 } // end namespace fawkes
void wait()
Wait until minimum loop time has been reached.
Definition: wait.cpp:81
static Clock * instance()
Clock initializer.
Definition: clock.cpp:65
void get_time(struct timeval *tv) const
Returns the time of the selected time source.
Definition: clock.cpp:176
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:239
This is supposed to be the central clock in Fawkes.
Definition: clock.h:34
A class for handling time.
Definition: time.h:91
void wait_systime()
Wait until minimum loop time has been reached in real time.
Definition: wait.cpp:100
long int time_diff_usec(const timeval &a, const timeval &b)
Get difference between two time structs in microseconds.
Definition: time.h:84
void mark_start()
Mark start of loop.
Definition: wait.cpp:70
~TimeWait()
Destructor.
Definition: wait.cpp:60