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 
gettimeofday(struct timeval * tp,void *)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 
fixup()94     void fixup() {
95         if (tv_usec < 0) {
96             tv_usec += 1000000;
97             --tv_sec;
98         }
99     }
100 
101 public:
102 
xtime(long sec,long usec)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 
xtime(long long usec)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
operator long long() const121     operator long long() const {return static_cast<long long>(tv_sec) * 1000000 + tv_usec;}
122 
operator +=(xtime rhs)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 
operator -=(xtime rhs)133     xtime& operator -= (xtime rhs) {
134         tv_sec -= rhs.tv_sec;
135         tv_usec -= rhs.tv_usec;
136         fixup();
137         return *this;
138     }
139 
operator %=(xtime rhs)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 
operator +(xtime x,xtime y)150     friend xtime operator+(xtime x, xtime y) {return x += y;}
operator -(xtime x,xtime y)151     friend xtime operator-(xtime x, xtime y) {return x -= y;}
operator %(xtime x,xtime y)152     friend xtime operator%(xtime x, xtime y) {return x %= y;}
153 
operator ==(xtime x,xtime y)154     friend bool operator==(xtime x, xtime y)
155         { return (x.tv_sec == y.tv_sec && x.tv_usec == y.tv_usec); }
156 
operator <(xtime x,xtime y)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 
operator !=(xtime x,xtime y)163     friend bool operator!=(xtime x, xtime y) { return !(x == y); }
operator >(xtime x,xtime y)164     friend bool operator> (xtime x, xtime y) { return y < x; }
operator <=(xtime x,xtime y)165     friend bool operator<=(xtime x, xtime y) { return !(y < x); }
operator >=(xtime x,xtime y)166     friend bool operator>=(xtime x, xtime y) { return !(x < y); }
167 
operator <<(std::ostream & os,xtime x)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
now()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, &ts );
205 
206     xtime xt( ts.tv_sec, ts.tv_nsec/1000);
207     return time_point(duration(xt));
208 #endif  // POSIX
209 
210 }
211 
test_xtime_clock()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 
main()232 int main()
233 {
234     timeval_demo::test_xtime_clock();
235     return 0;
236 }
237 
238