3 * Provides a class for managing a timestamp (seconds & milliseconds.)
6 // Written by Curtis Olson, started December 1998.
8 // Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License as
12 // published by the Free Software Foundation; either version 2 of the
13 // License, or (at your option) any later version.
15 // This program is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // General Public License for more details.
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #ifndef _TIMESTAMP_HXX
28 #define _TIMESTAMP_HXX
32 # error This library requires C++
38 #include <simgear/compiler.h>
39 #include <simgear/math/SGCMath.hxx>
42 * The SGTimeStamp class allows you to mark and compare time stamps
43 * with nanosecond accuracy (if your system has support for this
46 * The SGTimeStamp is useful for tracking the elapsed time of various
47 * events in your program. You can also use it to keep consistent
48 * motion across varying frame rates.
50 * Note SGTimestamp does not deliver the time of day. The content of this
51 * stamps might be, dependent on the implementation, a time to an arbitrary
57 typedef long sec_type;
58 typedef int nsec_type;
60 /** Default constructor, initialize time to zero. */
66 /** Hmm, might reenable them at some time, but since it is not clear
67 what the input unit of the int is, omit them for now.
68 Use the static constructor functions where it is clear from the method
69 name how the arguments are meant.
71 // SGTimeStamp(sec_type sec)
72 // { setTime(sec, 0); }
73 // SGTimeStamp(int sec)
74 // { setTime(sec, 0); }
75 // SGTimeStamp(const double& sec)
78 /** Update stored time to current time (seconds and nanoseconds) */
81 /** Set the time from a double value */
82 void setTime(const double& seconds)
84 sec_type wholeSecs = sec_type(floor(seconds));
86 reminder = nsec_type(floor((seconds - wholeSecs)*(1000*1000*1000)));
87 setTime(wholeSecs, reminder);
89 /** Set the time from a seconds/nanoseconds pair */
90 void setTime(sec_type sec, nsec_type nsec)
93 _sec = sec + nsec / (1000*1000*1000);
94 _nsec = nsec % (1000*1000*1000);
96 _sec = sec - 1 + nsec / (1000*1000*1000);
97 _nsec = (1000*1000*1000) + nsec % (1000*1000*1000);
102 /** @return the saved seconds of this time stamp */
103 long get_seconds() const { return _sec; }
105 /** @return the saved microseconds of this time stamp */
106 int get_usec() const { return _nsec/1000; }
108 /** @return the saved seconds of this time stamp */
109 const sec_type& getSeconds() const
111 /** @return the saved nanoseconds of this time stamp */
112 const nsec_type& getNanoSeconds() const
115 /** @return the value of the timestamp in nanoseconds,
116 * use doubles to avoid overflow.
117 * If you need real nanosecond accuracy for time differences, build up a
118 * SGTimeStamp reference time and compare SGTimeStamps directly.
120 double toNSecs() const
121 { return _nsec + double(_sec)*1000*1000*1000; }
123 /** @return the value of the timestamp in microseconds,
124 * use doubles to avoid overflow.
125 * If you need real nanosecond accuracy for time differences, build up a
126 * SGTimeStamp reference time and compare SGTimeStamps directly.
128 double toUSecs() const
129 { return 1e-3*_nsec + double(_sec)*1000*1000; }
131 /** @return the value of the timestamp in milliseconds,
132 * use doubles to avoid overflow.
133 * If you need real nanosecond accuracy for time differences, build up a
134 * SGTimeStamp reference time and compare SGTimeStamps directly.
136 double toMSecs() const
137 { return 1e-6*_nsec + double(_sec)*1000; }
139 /** @return the value of the timestamp in seconds,
140 * use doubles to avoid overflow.
141 * If you need real nanosecond accuracy for time differences, build up a
142 * SGTimeStamp reference time and compare SGTimeStamps directly.
144 double toSecs() const
145 { return 1e-9*_nsec + _sec; }
147 /** Inplace addition.
149 SGTimeStamp& operator+=(const SGTimeStamp& c)
153 if ((1000*1000*1000) <= _nsec) {
154 _nsec -= (1000*1000*1000);
160 /** Inplace subtraction.
162 SGTimeStamp& operator-=(const SGTimeStamp& c)
167 _nsec += (1000*1000*1000);
174 * Create SGTimeStamps from input with given units
176 static SGTimeStamp fromSecMSec(sec_type sec, nsec_type msec)
177 { return SGTimeStamp(sec, 1000*1000*msec); }
178 static SGTimeStamp fromSecUSec(sec_type sec, nsec_type usec)
179 { return SGTimeStamp(sec, 1000*usec); }
180 static SGTimeStamp fromSecNSec(sec_type sec, nsec_type nsec)
181 { return SGTimeStamp(sec, nsec); }
183 static SGTimeStamp fromSec(int sec)
184 { SGTimeStamp ts; ts.setTime(sec); return ts; }
185 static SGTimeStamp fromSec(const double& sec)
186 { SGTimeStamp ts; ts.setTime(sec); return ts; }
187 static SGTimeStamp fromMSec(nsec_type msec)
188 { return SGTimeStamp(0, 1000*1000*msec); }
189 static SGTimeStamp fromUSec(nsec_type usec)
190 { return SGTimeStamp(0, 1000*usec); }
191 static SGTimeStamp fromNSec(nsec_type nsec)
192 { return SGTimeStamp(0, nsec); }
195 * Return a timestamp with the current time.
197 static SGTimeStamp now()
198 { SGTimeStamp ts; ts.stamp(); return ts; }
201 * Sleep until the time of abstime is passed.
203 static bool sleepUntil(const SGTimeStamp& abstime);
208 static bool sleepFor(const SGTimeStamp& reltime);
211 * Alias for the most common use case with milliseconds.
213 static bool sleepForMSec(unsigned msec)
214 { return sleepFor(fromMSec(msec)); }
217 * elapsed time since the stamp was taken, in msec
219 int elapsedMSec() const;
221 SGTimeStamp(sec_type sec, nsec_type nsec)
222 { setTime(sec, nsec); }
229 operator==(const SGTimeStamp& c1, const SGTimeStamp& c2)
231 if (c1.getNanoSeconds() != c2.getNanoSeconds())
233 return c1.getSeconds() == c2.getSeconds();
237 operator!=(const SGTimeStamp& c1, const SGTimeStamp& c2)
238 { return !operator==(c1, c2); }
241 operator<(const SGTimeStamp& c1, const SGTimeStamp& c2)
243 if (c1.getSeconds() < c2.getSeconds())
245 if (c1.getSeconds() > c2.getSeconds())
247 return c1.getNanoSeconds() < c2.getNanoSeconds();
251 operator>(const SGTimeStamp& c1, const SGTimeStamp& c2)
255 operator>=(const SGTimeStamp& c1, const SGTimeStamp& c2)
256 { return !(c1 < c2); }
259 operator<=(const SGTimeStamp& c1, const SGTimeStamp& c2)
260 { return !(c1 > c2); }
263 operator+(const SGTimeStamp& c1)
267 operator-(const SGTimeStamp& c1)
268 { return SGTimeStamp::fromSec(0) -= c1; }
271 operator+(const SGTimeStamp& c1, const SGTimeStamp& c2)
272 { return SGTimeStamp(c1) += c2; }
275 operator-(const SGTimeStamp& c1, const SGTimeStamp& c2)
276 { return SGTimeStamp(c1) -= c2; }
278 template<typename char_type, typename traits_type>
280 std::basic_ostream<char_type, traits_type>&
281 operator<<(std::basic_ostream<char_type, traits_type>& os, const SGTimeStamp& c)
283 std::basic_stringstream<char_type, traits_type> stream;
286 if (c.getSeconds() < 0) {
287 stream << stream.widen('-');
290 stream << pos.getSeconds() << stream.widen('.');
291 stream << std::setw(9) << std::setfill('0') << pos.getNanoSeconds();
293 return os << stream.str();
296 #endif // _TIMESTAMP_HXX