]> git.mxchange.org Git - simgear.git/blob - simgear/timing/timestamp.hxx
Make use of posix clocks if available.
[simgear.git] / simgear / timing / timestamp.hxx
1 /**
2  * \file timestamp.hxx
3  * Provides a class for managing a timestamp (seconds & milliseconds.)
4  */
5
6 // Written by Curtis Olson, started December 1998.
7 //
8 // Copyright (C) 1998  Curtis L. Olson  - http://www.flightgear.org/~curt
9 //
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.
14 //
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.
19 //
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.
23 //
24 // $Id$
25
26
27 #ifndef _TIMESTAMP_HXX
28 #define _TIMESTAMP_HXX
29
30
31 #ifndef __cplusplus
32 # error This library requires C++
33 #endif
34
35 #include <iosfwd>
36 #include <iomanip>
37 #include <sstream>
38 #include <simgear/compiler.h>
39 #include <simgear/math/SGCMath.hxx>
40
41 /**
42  * The SGTimeStamp class allows you to mark and compare time stamps
43  * with nanosecond accuracy (if your system has support for this
44  * level of accuracy).
45  *
46  * The SGTimeStamp is useful for tracking the elapsed time of various
47  * events in your program. You can also use it to keep constistant
48  * motion across varying frame rates.
49  *
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
52  * base time.
53  */
54
55 class SGTimeStamp {
56 public:
57     typedef long sec_type;
58     typedef int nsec_type;
59
60     /** Default constructor, initialize time to zero. */
61     SGTimeStamp() :
62       _sec(0),
63       _nsec(0)
64     { }
65
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.
70      */
71 //     SGTimeStamp(sec_type sec)
72 //     { setTime(sec, 0); }
73 //     SGTimeStamp(int sec)
74 //     { setTime(sec, 0); }
75 //     SGTimeStamp(const double& sec)
76 //     { setTime(sec); }
77
78     /** Update stored time to current time (seconds and nanoseconds) */
79     void stamp();
80
81     /** Set the time from a double value */
82     void setTime(const double& seconds)
83     {
84         sec_type wholeSecs = sec_type(floor(seconds));
85         nsec_type reminder;
86         reminder = nsec_type(floor((seconds - wholeSecs)*(1000*1000*1000)));
87         setTime(wholeSecs, reminder);
88     }
89     /** Set the time from a seconds/nanoseconds pair */
90     void setTime(sec_type sec, nsec_type nsec)
91     {
92         if (0 <= nsec) {
93             _sec = sec + nsec / (1000*1000*1000);
94             _nsec = nsec % (1000*1000*1000);
95         } else {
96             _sec = sec - 1 + nsec / (1000*1000*1000);
97             _nsec = (1000*1000*1000) + nsec % (1000*1000*1000);
98         }
99     }
100
101     
102     /** @return the saved seconds of this time stamp */
103     long get_seconds() const { return _sec; }
104
105     /** @return the saved microseconds of this time stamp */
106     int get_usec() const { return _nsec/1000; }
107
108     /** @return the saved seconds of this time stamp */
109     const sec_type& getSeconds() const
110     { return _sec; }
111     /** @return the saved nanoseconds of this time stamp */
112     const nsec_type& getNanoSeconds() const
113     { return _nsec; }
114
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.
119      */
120     double toNSecs() const
121     { return _nsec + double(_sec)*1000*1000*1000; }
122
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.
127      */
128     double toUSecs() const
129     { return 1e-3*_nsec + double(_sec)*1000*1000; }
130
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.
135      */
136     double toMSecs() const
137     { return 1e-6*_nsec + double(_sec)*1000; }
138
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.
143      */
144     double toSecs() const
145     { return 1e-9*_nsec + _sec; }
146
147     /** Inplace addition.
148      */
149     SGTimeStamp& operator+=(const SGTimeStamp& c)
150     {
151         _sec += c._sec;
152         _nsec += c._nsec;
153         if ((1000*1000*1000) <= _nsec) {
154             _nsec -= (1000*1000*1000);
155             _sec += 1;
156         }
157         return *this;
158     }
159
160     /** Inplace subtraction.
161      */
162     SGTimeStamp& operator-=(const SGTimeStamp& c)
163     {
164         _sec -= c._sec;
165         _nsec -= c._nsec;
166         if (_nsec < 0) {
167             _nsec += (1000*1000*1000);
168             _sec -= 1;
169         }
170         return *this;
171     }
172
173     /**
174      *  Create SGTimeStamps from input with given units 
175      */
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); }
182
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 fromUSec(nsec_type usec)
188     { return SGTimeStamp(0, 1000*usec); }
189     static SGTimeStamp fromNSec(nsec_type nsec)
190     { return SGTimeStamp(0, nsec); }
191
192     /**
193      *  Return a timestamp with the current time.
194      */
195     static SGTimeStamp now()
196     { SGTimeStamp ts; ts.stamp(); return ts; }
197
198 private:
199     SGTimeStamp(sec_type sec, nsec_type nsec)
200     { setTime(sec, nsec); }
201
202     nsec_type _nsec;
203     sec_type _sec;
204 };
205
206 inline bool
207 operator==(const SGTimeStamp& c1, const SGTimeStamp& c2)
208 {
209   if (c1.getNanoSeconds() != c2.getNanoSeconds())
210     return false;
211   return c1.getSeconds() == c2.getSeconds();
212 }
213
214 inline bool
215 operator!=(const SGTimeStamp& c1, const SGTimeStamp& c2)
216 { return !operator==(c1, c2); }
217
218 inline bool
219 operator<(const SGTimeStamp& c1, const SGTimeStamp& c2)
220 {
221   if (c1.getSeconds() < c2.getSeconds())
222     return true;
223   if (c1.getSeconds() > c2.getSeconds())
224     return false;
225   return c1.getNanoSeconds() < c2.getNanoSeconds();
226 }
227
228 inline bool
229 operator>(const SGTimeStamp& c1, const SGTimeStamp& c2)
230 { return c2 < c1; }
231
232 inline bool
233 operator>=(const SGTimeStamp& c1, const SGTimeStamp& c2)
234 { return !(c1 < c2); }
235
236 inline bool
237 operator<=(const SGTimeStamp& c1, const SGTimeStamp& c2)
238 { return !(c1 > c2); }
239
240 inline SGTimeStamp
241 operator+(const SGTimeStamp& c1)
242 { return c1; }
243
244 inline SGTimeStamp
245 operator-(const SGTimeStamp& c1)
246 { return SGTimeStamp::fromSec(0) -= c1; }
247
248 inline SGTimeStamp
249 operator+(const SGTimeStamp& c1, const SGTimeStamp& c2)
250 { return SGTimeStamp(c1) += c2; }
251
252 inline SGTimeStamp
253 operator-(const SGTimeStamp& c1, const SGTimeStamp& c2)
254 { return SGTimeStamp(c1) -= c2; }
255
256 template<typename char_type, typename traits_type> 
257 inline
258 std::basic_ostream<char_type, traits_type>&
259 operator<<(std::basic_ostream<char_type, traits_type>& os, const SGTimeStamp& c)
260 {
261   std::basic_stringstream<char_type, traits_type> stream;
262
263   SGTimeStamp pos = c;
264   if (c.getSeconds() < 0) {
265     stream << stream.widen('-');
266     pos = - c;
267   }
268   stream << pos.getSeconds() << stream.widen('.');
269   stream << std::setw(9) << std::setfill('0') << pos.getNanoSeconds();
270
271   return os << stream.str();
272 }
273
274 #endif // _TIMESTAMP_HXX
275
276