1 | // timeval_demo.cpp ----------------------------------------------------------// |
2 | |
3 | // Copyright 2008 Howard Hinnant |
4 | // Copyright 2008 Beman Dawes |
5 | // Copyright 2009 Vicente J. Botet Escriba |
6 | // Copyright (c) Microsoft Corporation 2014 |
7 | |
8 | // Distributed under the Boost Software License, Version 1.0. |
9 | // See http://www.boost.org/LICENSE_1_0.txt |
10 | |
11 | /* |
12 | This code was extracted by Vicente J. Botet Escriba from Beman Dawes time2_demo.cpp which |
13 | was derived by Beman Dawes from Howard Hinnant's time2_demo prototype. |
14 | Many thanks to Howard for making his code available under the Boost license. |
15 | The original code was modified to conform to Boost conventions and to section |
16 | 20.9 Time utilities [time] of the C++ committee's working paper N2798. |
17 | See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf. |
18 | |
19 | time2_demo contained this comment: |
20 | |
21 | Much thanks to Andrei Alexandrescu, |
22 | Walter Brown, |
23 | Peter Dimov, |
24 | Jeff Garland, |
25 | Terry Golubiewski, |
26 | Daniel Krugler, |
27 | Anthony Williams. |
28 | */ |
29 | #define _CRT_SECURE_NO_WARNINGS // disable VC++ foolishness |
30 | |
31 | #include <boost/chrono/chrono.hpp> |
32 | #include <boost/type_traits.hpp> |
33 | |
34 | #include <iostream> |
35 | |
36 | #if defined(BOOST_CHRONO_MAC_API) |
37 | #include <sys/time.h> //for gettimeofday and timeval |
38 | #endif |
39 | |
40 | #if defined(BOOST_CHRONO_WINDOWS_API) |
41 | # include <windows.h> |
42 | #endif |
43 | |
44 | #if defined(BOOST_CHRONO_WINDOWS_API) |
45 | |
46 | namespace |
47 | { |
48 | #if defined UNDER_CE || BOOST_PLAT_WINDOWS_RUNTIME |
49 | // Windows CE and Windows store does not define timeval |
50 | struct timeval { |
51 | long tv_sec; /* seconds */ |
52 | long tv_usec; /* and microseconds */ |
53 | }; |
54 | #endif |
55 | |
56 | int gettimeofday(struct timeval * tp, void *) |
57 | { |
58 | FILETIME ft; |
59 | #if defined(UNDER_CE) |
60 | // Windows CE does not define GetSystemTimeAsFileTime so we do it in two steps. |
61 | SYSTEMTIME st; |
62 | ::GetSystemTime( &st ); |
63 | ::SystemTimeToFileTime( &st, &ft ); |
64 | #else |
65 | ::GetSystemTimeAsFileTime( &ft ); // never fails |
66 | #endif |
67 | long long t = (static_cast<long long>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime; |
68 | # if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0 |
69 | t -= 116444736000000000LL; |
70 | # else |
71 | t -= 116444736000000000; |
72 | # endif |
73 | t /= 10; // microseconds |
74 | tp->tv_sec = static_cast<long>( t / 1000000UL); |
75 | tp->tv_usec = static_cast<long>( t % 1000000UL); |
76 | return 0; |
77 | } |
78 | } // unnamed namespace |
79 | |
80 | #endif |
81 | |
82 | // timeval clock demo |
83 | // Demonstrate the use of a timeval-like struct to be used as the representation |
84 | // type for both duraiton and time_point. |
85 | |
86 | namespace timeval_demo |
87 | { |
88 | |
89 | class xtime { |
90 | private: |
91 | long tv_sec; |
92 | long tv_usec; |
93 | |
94 | void fixup() { |
95 | if (tv_usec < 0) { |
96 | tv_usec += 1000000; |
97 | --tv_sec; |
98 | } |
99 | } |
100 | |
101 | public: |
102 | |
103 | explicit xtime(long sec, long usec) { |
104 | tv_sec = sec; |
105 | tv_usec = usec; |
106 | if (tv_usec < 0 || tv_usec >= 1000000) { |
107 | tv_sec += tv_usec / 1000000; |
108 | tv_usec %= 1000000; |
109 | fixup(); |
110 | } |
111 | } |
112 | |
113 | explicit xtime(long long usec) |
114 | { |
115 | tv_usec = static_cast<long>(usec % 1000000); |
116 | tv_sec = static_cast<long>(usec / 1000000); |
117 | fixup(); |
118 | } |
119 | |
120 | // explicit |
121 | operator long long() const {return static_cast<long long>(tv_sec) * 1000000 + tv_usec;} |
122 | |
123 | xtime& operator += (xtime rhs) { |
124 | tv_sec += rhs.tv_sec; |
125 | tv_usec += rhs.tv_usec; |
126 | if (tv_usec >= 1000000) { |
127 | tv_usec -= 1000000; |
128 | ++tv_sec; |
129 | } |
130 | return *this; |
131 | } |
132 | |
133 | xtime& operator -= (xtime rhs) { |
134 | tv_sec -= rhs.tv_sec; |
135 | tv_usec -= rhs.tv_usec; |
136 | fixup(); |
137 | return *this; |
138 | } |
139 | |
140 | xtime& operator %= (xtime rhs) { |
141 | long long t = tv_sec * 1000000 + tv_usec; |
142 | long long r = rhs.tv_sec * 1000000 + rhs.tv_usec; |
143 | t %= r; |
144 | tv_sec = static_cast<long>(t / 1000000); |
145 | tv_usec = static_cast<long>(t % 1000000); |
146 | fixup(); |
147 | return *this; |
148 | } |
149 | |
150 | friend xtime operator+(xtime x, xtime y) {return x += y;} |
151 | friend xtime operator-(xtime x, xtime y) {return x -= y;} |
152 | friend xtime operator%(xtime x, xtime y) {return x %= y;} |
153 | |
154 | friend bool operator==(xtime x, xtime y) |
155 | { return (x.tv_sec == y.tv_sec && x.tv_usec == y.tv_usec); } |
156 | |
157 | friend bool operator<(xtime x, xtime y) { |
158 | if (x.tv_sec == y.tv_sec) |
159 | return (x.tv_usec < y.tv_usec); |
160 | return (x.tv_sec < y.tv_sec); |
161 | } |
162 | |
163 | friend bool operator!=(xtime x, xtime y) { return !(x == y); } |
164 | friend bool operator> (xtime x, xtime y) { return y < x; } |
165 | friend bool operator<=(xtime x, xtime y) { return !(y < x); } |
166 | friend bool operator>=(xtime x, xtime y) { return !(x < y); } |
167 | |
168 | friend std::ostream& operator<<(std::ostream& os, xtime x) |
169 | {return os << '{' << x.tv_sec << ',' << x.tv_usec << '}';} |
170 | }; |
171 | |
172 | class xtime_clock |
173 | { |
174 | public: |
175 | typedef xtime rep; |
176 | typedef boost::micro period; |
177 | typedef boost::chrono::duration<rep, period> duration; |
178 | typedef boost::chrono::time_point<xtime_clock> time_point; |
179 | |
180 | static time_point now(); |
181 | }; |
182 | |
183 | |
184 | xtime_clock::time_point |
185 | xtime_clock::now() |
186 | { |
187 | #if defined(BOOST_CHRONO_WINDOWS_API) |
188 | timeval tv; |
189 | gettimeofday(&tv, 0); |
190 | xtime xt( tv.tv_sec, tv.tv_usec); |
191 | return time_point(duration(xt)); |
192 | |
193 | #elif defined(BOOST_CHRONO_MAC_API) |
194 | |
195 | timeval tv; |
196 | gettimeofday(&tv, 0); |
197 | xtime xt( tv.tv_sec, tv.tv_usec); |
198 | return time_point(duration(xt)); |
199 | |
200 | #elif defined(BOOST_CHRONO_POSIX_API) |
201 | //time_point t(0,0); |
202 | |
203 | timespec ts; |
204 | ::clock_gettime( CLOCK_REALTIME, tp: &ts ); |
205 | |
206 | xtime xt( ts.tv_sec, ts.tv_nsec/1000); |
207 | return time_point(duration(xt)); |
208 | #endif // POSIX |
209 | |
210 | } |
211 | |
212 | void test_xtime_clock() |
213 | { |
214 | using namespace boost::chrono; |
215 | std::cout << "timeval_demo system clock test\n" ; |
216 | std::cout << "sizeof xtime_clock::time_point = " << sizeof(xtime_clock::time_point) << '\n'; |
217 | std::cout << "sizeof xtime_clock::duration = " << sizeof(xtime_clock::duration) << '\n'; |
218 | std::cout << "sizeof xtime_clock::rep = " << sizeof(xtime_clock::rep) << '\n'; |
219 | xtime_clock::duration delay(milliseconds(5)); |
220 | xtime_clock::time_point start = xtime_clock::now(); |
221 | |
222 | while (xtime_clock::now() - start <= delay) |
223 | { |
224 | } |
225 | xtime_clock::time_point stop = xtime_clock::now(); |
226 | xtime_clock::duration elapsed = stop - start; |
227 | std::cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n" ; |
228 | } |
229 | |
230 | } // timeval_demo |
231 | |
232 | int main() |
233 | { |
234 | timeval_demo::test_xtime_clock(); |
235 | return 0; |
236 | } |
237 | |
238 | |