]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
2 | <html><head> | |
3 | <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> | |
4 | ||
5 | ||
6 | <title>time2_demo</title> | |
7 | </head><body> | |
8 | ||
9 | <pre><font color="#c80000">/* | |
10 | Copyright (c) 2008 Howard Hinnant | |
11 | ||
12 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
13 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
14 | ||
15 | ||
16 | A prototype of a proposal for a time/duration/clock library for the C++ standard. | |
17 | It is intended that this be a solid foundation upon which higher level libraries | |
18 | can be based. Examples of such libraries include a date/time library and a | |
19 | physical quantities library. | |
20 | ||
21 | Two general purpose facilities are proposed: | |
22 | ||
23 | common_type | |
24 | ratio | |
25 | ||
26 | And 5 time/duration/clock facilities are proposed | |
27 | ||
28 | duration | |
29 | time_point | |
30 | system_clock | |
31 | monotonic_clock <font color="#c80000">// optional</font> | |
32 | high_resolution_clock <font color="#c80000">// optional</font> | |
33 | ||
34 | Much thanks to Andrei Alexandrescu, | |
35 | Walter Brown, | |
36 | Peter Dimov, | |
37 | Jeff Garland, | |
38 | Terry Golubiewski, | |
39 | Daniel Krügler, | |
40 | Anthony Williams. | |
41 | ||
42 | Synopsis | |
43 | ||
44 | namespace std | |
45 | { | |
46 | ||
47 | <font color="#c80000">// <type_traits></font> | |
48 | ||
49 | <font color="#c80000">// common_type</font> | |
50 | ||
51 | <font color="#c80000">// common_type is ageneral purpose trait that can be specialized for user-defined types.</font> | |
52 | <font color="#c80000">// The semantics are intended to be identical to finding the resulting type of a</font> | |
53 | <font color="#c80000">// the conditional operator.</font> | |
54 | <font color="#c80000">// The client may need to specialize common_type if he wishes to convert to or from</font> | |
55 | <font color="#c80000">// another type only explicitly. It is used to determine the result type</font> | |
56 | <font color="#c80000">// in "mixed-mode" duration and time_point arithmetic. It will also find use in</font> | |
57 | <font color="#c80000">// similar "mixed-mode" arithmetic applications.</font> | |
58 | ||
59 | template <class T, class U> | |
60 | struct common_type | |
61 | { | |
62 | private: | |
63 | static T t(); | |
64 | static U u(); | |
65 | public: | |
66 | typedef decltype(true ? t() : u()) type; | |
67 | }; | |
68 | ||
69 | <font color="#c80000">// or...</font> | |
70 | ||
71 | template <class ...T> struct common_type; | |
72 | ||
73 | template <class T> | |
74 | struct common_type<T> | |
75 | { | |
76 | typedef T type; | |
77 | }; | |
78 | ||
79 | template <class T, class U> | |
80 | struct common_type<T, U> | |
81 | { | |
82 | private: | |
83 | static T t(); | |
84 | static U u(); | |
85 | public: | |
86 | typedef decltype(true ? t() : u()) type; | |
87 | }; | |
88 | ||
89 | template <class T, class U, class ...V> | |
90 | struct common_type<T, U, V...> | |
91 | { | |
92 | typedef typename common_type<typename common_type<T, U>::type, V...>::type type; | |
93 | }; | |
94 | ||
95 | <font color="#c80000">// This alternative variadic formulation of common_type has some advantages:</font> | |
96 | <font color="#c80000">//</font> | |
97 | <font color="#c80000">// 1. The obvious advantage is that it can handle 3 or more arguments seamlessly.</font> | |
98 | <font color="#c80000">// This can come in handy when writing template functions that take more than</font> | |
99 | <font color="#c80000">// two arguments, such as fma(x, y, z).</font> | |
100 | <font color="#c80000">//</font> | |
101 | <font color="#c80000">// 2. We could just get rid of identity (avoiding the legacy conflict) and use</font> | |
102 | <font color="#c80000">// common_type<T>::type in the one place we use identity<T>::type today.</font> | |
103 | <font color="#c80000">//</font> | |
104 | <font color="#c80000">// 3. For clients that need to specialize common_type (such as duration and time_point),</font> | |
105 | <font color="#c80000">// the client still needs to specialize only the two-argument version. The default</font> | |
106 | <font color="#c80000">// definition of the higher-order common_type will automatically use the client's</font> | |
107 | <font color="#c80000">// specialized two-argument version.</font> | |
108 | <font color="#c80000">// For example:</font> | |
109 | <font color="#c80000">// common_type<duration<double>, hours, microseconds>::type is duration<double, micro></font> | |
110 | ||
111 | <font color="#c80000">// ... end or</font> | |
112 | ||
113 | <font color="#c80000">// The cost of not including either version of common_type is that it is very likely that</font> | |
114 | <font color="#c80000">// the implementation would include it anyway, but spell it __common_type instead. This</font> | |
115 | <font color="#c80000">// would prevent authors of arithmetic emulators from using their classes as representations</font> | |
116 | <font color="#c80000">// with durations unless the emulator had exactly one implicit conversion to or from an</font> | |
117 | <font color="#c80000">// arithmetic type. This would be a large loss of functionality from the client's point</font> | |
118 | <font color="#c80000">// of view, possibly mandating a less safe interface for the client's arithmetic emulator.</font> | |
119 | ||
120 | <font color="#c80000">// ratio</font> | |
121 | ||
122 | <font color="#c80000">// ratio is a general purpose type allowing one to easily and safely compute integral</font> | |
123 | <font color="#c80000">// ratio values at compile time. The ratio class catches all errors (such as divide by</font> | |
124 | <font color="#c80000">// zero and overflow) at compile time. It is used in the duration and time_point libraries</font> | |
125 | <font color="#c80000">// to efficiently create units of time. It can also be used in other "quantity"</font> | |
126 | <font color="#c80000">// libraries (both std-defined and user-defined), or anywhere there is an integral</font> | |
127 | <font color="#c80000">// ratio which is known at compile time. The use of this utility can greatly reduce</font> | |
128 | <font color="#c80000">// the chances of run time overflow because the ratio (and any ratios resulting from</font> | |
129 | <font color="#c80000">// ratio arithmetic) are always reduced to lowest terms.</font> | |
130 | ||
131 | <font color="#c80000">// The cost of not including ratio would mean that the implementor would likely have this</font> | |
132 | <font color="#c80000">// functionality anyway, but spell it __ratio instead. This would prevent the client from</font> | |
133 | <font color="#c80000">// using ratio in his own code as demonstrated in the "User1" example. Furthermore duration</font> | |
134 | <font color="#c80000">// would have to be templated on two long long's instead of on ratio like so:</font> | |
135 | <font color="#c80000">//</font> | |
136 | <font color="#c80000">// template <class Rep, long long N, long long D> duration.</font> | |
137 | <font color="#c80000">//</font> | |
138 | <font color="#c80000">// This would mean that clients wanting to build a custom duration type (say a nanosecond</font> | |
139 | <font color="#c80000">// represented by a double) would have to write:</font> | |
140 | <font color="#c80000">//</font> | |
141 | <font color="#c80000">// duration<double, 1, 1000000000LL></font> | |
142 | <font color="#c80000">//</font> | |
143 | <font color="#c80000">// instead of:</font> | |
144 | <font color="#c80000">//</font> | |
145 | <font color="#c80000">// duration<double, nano></font> | |
146 | <font color="#c80000">//</font> | |
147 | <font color="#c80000">// This lack of syntatic niceness, along with the loss of functionality in the reuse of</font> | |
148 | <font color="#c80000">// ratio in user-written code seems to indicate that the loss of ratio would be a sizeable</font> | |
149 | <font color="#c80000">// loss to client code.</font> | |
150 | ||
151 | template <intmax_t N, intmax_t D = 1> | |
152 | class ratio | |
153 | { | |
154 | <font color="#c80000">// For every possible value of N and D, abs(N) >= 0 and abs(D) > 0</font> | |
155 | static_assert(__static_abs<N>::value >= 0, "ratio numerator is out of range"); | |
156 | static_assert(__static_abs<D>::value > 0, "ratio denominator is out of range"); | |
157 | public: | |
158 | static const intmax_t num; <font color="#c80000">// Reduced by greatest common divisor of N and D, has sign of sign(N) * sign(D)</font> | |
159 | static const intmax_t den; <font color="#c80000">// Reduced by greatest common divisor of N and D, always positive</font> | |
160 | <font color="#c80000">// When num == 0, den == 1</font> | |
161 | }; | |
162 | ||
163 | <font color="#c80000">// The static_asserts in ratio are there to catch any values which have a negative absolute value.</font> | |
164 | <font color="#c80000">// In a typical 2's complement representation this is only LLONG_MIN. The reason for prohibiting</font> | |
165 | <font color="#c80000">// this value is because ratio must take the absolute values of its arguments and generally depends</font> | |
166 | <font color="#c80000">// on that number being non-negative in order to maintain invariants such as den > 0.</font> | |
167 | ||
168 | <font color="#c80000">// convenience typedefs</font> | |
169 | ||
170 | typedef ratio<1, 1000000000000000000000000> yocto; <font color="#c80000">// conditionally supported</font> | |
171 | typedef ratio<1, 1000000000000000000000> zepto; <font color="#c80000">// conditionally supported</font> | |
172 | typedef ratio<1, 1000000000000000000> atto; | |
173 | typedef ratio<1, 1000000000000000> femto; | |
174 | typedef ratio<1, 1000000000000> pico; | |
175 | typedef ratio<1, 1000000000> nano; | |
176 | typedef ratio<1, 1000000> micro; | |
177 | typedef ratio<1, 1000> milli; | |
178 | typedef ratio<1, 100> centi; | |
179 | typedef ratio<1, 10> deci; | |
180 | typedef ratio< 10, 1> deca; | |
181 | typedef ratio< 100, 1> hecto; | |
182 | typedef ratio< 1000, 1> kilo; | |
183 | typedef ratio< 1000000, 1> mega; | |
184 | typedef ratio< 1000000000, 1> giga; | |
185 | typedef ratio< 1000000000000, 1> tera; | |
186 | typedef ratio< 1000000000000000, 1> peta; | |
187 | typedef ratio< 1000000000000000000, 1> exa; | |
188 | typedef ratio< 1000000000000000000000, 1> zetta; <font color="#c80000">// conditionally supported</font> | |
189 | typedef ratio<1000000000000000000000000, 1> yotta; <font color="#c80000">// conditionally supported</font> | |
190 | ||
191 | <font color="#c80000">// Compile time arithmetic and comparisons should either avoid overflow or not compile</font> | |
192 | ||
193 | template <class R1, class R2> | |
194 | requires R1 and R2 are instantiations of ratio | |
195 | struct ratio_add | |
196 | { | |
197 | typedef ratio<pseudo code: R1 + R2> type; | |
198 | }; | |
199 | ||
200 | template <class R1, class R2> | |
201 | requires R1 and R2 are instantiations of ratio | |
202 | struct ratio_subtract | |
203 | { | |
204 | typedef ratio<pseudo code: R1 - R2> type; | |
205 | }; | |
206 | ||
207 | template <class R1, class R2> | |
208 | requires R1 and R2 are instantiations of ratio | |
209 | struct ratio_multiply | |
210 | { | |
211 | typedef ratio<pseudo code: R1 * R2> type; | |
212 | }; | |
213 | ||
214 | template <class R1, class R2> | |
215 | requires R1 and R2 are instantiations of ratio | |
216 | struct ratio_divide | |
217 | { | |
218 | typedef ratio<pseudo code: R1 / R2> type; | |
219 | }; | |
220 | ||
221 | template <class R1, class R2> | |
222 | requires R1 and R2 are instantiations of ratio | |
223 | struct ratio_equal | |
224 | : public integral_constant<bool, pseudo code: R1 == R2> {}; | |
225 | ||
226 | template <class R1, class R2> | |
227 | requires R1 and R2 are instantiations of ratio | |
228 | struct ratio_not_equal | |
229 | : public integral_constant<bool, !ratio_equal<R1, R2>::value> {}; | |
230 | ||
231 | template <class R1, class R2> | |
232 | requires R1 and R2 are instantiations of ratio | |
233 | struct ratio_less | |
234 | : public integral_constant<bool, pseudo code: R1 < R2> {}; | |
235 | ||
236 | template <class R1, class R2> | |
237 | requires R1 and R2 are instantiations of ratio | |
238 | struct ratio_less_equal | |
239 | : public integral_constant<bool, !ratio_less<R2, R1>::value> {}; | |
240 | ||
241 | template <class R1, class R2> | |
242 | requires R1 and R2 are instantiations of ratio | |
243 | struct ratio_greater | |
244 | : public integral_constant<bool, ratio_less<R2, R1>::value> {}; | |
245 | ||
246 | template <class R1, class R2> | |
247 | requires R1 and R2 are instantiations of ratio | |
248 | struct ratio_greater_equal | |
249 | : public integral_constant<bool, !ratio_less<R1, R2>::value> {}; | |
250 | ||
251 | namespace datetime | |
252 | { | |
253 | ||
254 | <font color="#c80000">// duration customization traits</font> | |
255 | ||
256 | <font color="#c80000">// Authors of arithmetic emulation types should specialize treat_as_floating_point</font> | |
257 | <font color="#c80000">// if their class emulates floating point and they want to use it as a duration's</font> | |
258 | <font color="#c80000">// representation.</font> | |
259 | ||
260 | template <class Rep> struct treat_as_floating_point | |
261 | : is_floating_point<Rep> {}; | |
262 | ||
263 | <font color="#c80000">// Authors of arithmetic emulation types should specialize duration_values</font> | |
264 | <font color="#c80000">// if they want to use it as a duration's representation, and the default</font> | |
265 | <font color="#c80000">// definition of duration_values does not have the correct behavior.</font> | |
266 | ||
267 | template <class Rep> | |
268 | struct duration_values | |
269 | { | |
270 | public: | |
271 | static constexpr Rep zero() {return Rep(0);} | |
272 | static constexpr Rep max() {return numeric_limits<Rep>::max();} | |
273 | static constexpr Rep min() {return -max();} | |
274 | }; | |
275 | ||
276 | <font color="#c80000">// Note: Rep(0) instead of Rep() is used for zero() because the author of Rep may</font> | |
277 | <font color="#c80000">// chose to have Rep() refer to an inderminant or unitialized value.</font> | |
278 | ||
279 | <font color="#c80000">// duration</font> | |
280 | ||
281 | <font color="#c80000">// A duration has a representation and a period.</font> | |
282 | <font color="#c80000">// </font> | |
283 | <font color="#c80000">// The representation is an arithmetic type, or a class emulating an arithmetic type.</font> | |
284 | <font color="#c80000">//</font> | |
285 | <font color="#c80000">// The period is the rational number of seconds between "ticks" of the duration. The</font> | |
286 | <font color="#c80000">// duration simply holds a count of the elapsed number of ticks (using the</font> | |
287 | <font color="#c80000">// representation), and that is related to seconds by multiplying by the period.</font> | |
288 | <font color="#c80000">// Note, this multiplication is only required when one needs to convert between</font> | |
289 | <font color="#c80000">// durations with different tick periods (e.g. milliseconds to microseconds).</font> | |
290 | <font color="#c80000">// </font> | |
291 | <font color="#c80000">// A duration has defalt construction and default copy semantics. One can also explicitly</font> | |
292 | <font color="#c80000">// construct a duration from its representation or something implicitly convertible to</font> | |
293 | <font color="#c80000">// its representation. If the representation is integral (or emulated integral) the</font> | |
294 | <font color="#c80000">// duration may not be constructed from a floating point (or emulated floating point)</font> | |
295 | <font color="#c80000">// type, even if that type is impilcitly convertible to the representation (the client</font> | |
296 | <font color="#c80000">// must explicitly convert such an argument as they pass it to the constructor if such</font> | |
297 | <font color="#c80000">// a conversion is desired).</font> | |
298 | <font color="#c80000">// </font> | |
299 | <font color="#c80000">// A duration may be implicitly constructible from another duration if the representations</font> | |
300 | <font color="#c80000">// of the two durations meet certain requirements. Let the representation of this duration</font> | |
301 | <font color="#c80000">// be Rep1 and the representation of the other duration be Rep2. Example representations</font> | |
302 | <font color="#c80000">// include int, long long, double, or a user-defined class which emulates one of these</font> | |
303 | <font color="#c80000">// arithmetic types. To qualify for implicit constructability Rep1 must be explicitly</font> | |
304 | <font color="#c80000">// constructible from Rep2. Note that implicit constructibility of Rep1 from Rep2 is not</font> | |
305 | <font color="#c80000">// required for this implicit construction between durations. Additionally the trait</font> | |
306 | <font color="#c80000">// common_type<Rep1, Rep2>::type must be well defined. If a conditional expression involving</font> | |
307 | <font color="#c80000">// these two types isn't valid, there must exist a common_type specialization which makes</font> | |
308 | <font color="#c80000">// the trait valid.</font> | |
309 | <font color="#c80000">// </font> | |
310 | <font color="#c80000">// The requirements put on the relationship between Rep1 and Rep2 are intended to be minimal,</font> | |
311 | <font color="#c80000">// and not require implicit conversions (which could be considered error prone by the author</font> | |
312 | <font color="#c80000">// of either of these representations).</font> | |
313 | <font color="#c80000">// </font> | |
314 | <font color="#c80000">// In addition to the above relationship between the representations, implicit constructability</font> | |
315 | <font color="#c80000">// also depends on whether the representation is considered floating point (or emulated floating</font> | |
316 | <font color="#c80000">// point) or integral (or emulated integral).</font> | |
317 | <font color="#c80000">// </font> | |
318 | <font color="#c80000">// If a duration has a floating point (or emulated floating point) representation it</font> | |
319 | <font color="#c80000">// is implicitly constructible from all other durations of any period (as long as</font> | |
320 | <font color="#c80000">// the representations are compatible as described above).</font> | |
321 | <font color="#c80000">// </font> | |
322 | <font color="#c80000">// If a duration has an integral (or emulated integral) representation it is implicitly</font> | |
323 | <font color="#c80000">// constructible from other integral-based durations which have a period which will exactly convert</font> | |
324 | <font color="#c80000">// to the period of this duration with no truncation error. More specifically, if the</font> | |
325 | <font color="#c80000">// period of this duration is P1, and the period of the other duration is P2, this</font> | |
326 | <font color="#c80000">// duration is implicitly constructible from the other duration if P2/P1 is a whole number</font> | |
327 | <font color="#c80000">// (as long as the representations are compatible as described above). Example:</font> | |
328 | <font color="#c80000">// microseconds has a period p1 = 1/1000000 seconds. milliseconds has a period</font> | |
329 | <font color="#c80000">// P2 = 1/1000 seconds. P2/P1 is (1/1000)/(1/1000000) = 1000000/1000 = 1000.</font> | |
330 | <font color="#c80000">// Therefore microseconds will implicitly construct from milliseconds (but not vice-versa).</font> | |
331 | <font color="#c80000">//</font> | |
332 | <font color="#c80000">// These rules involving integral representations are meant to prevent accidental truncatation</font> | |
333 | <font color="#c80000">// error. If truncation error is desired, a duration_cast facility is available to force it.</font> | |
334 | <font color="#c80000">// Example:</font> | |
335 | <font color="#c80000">// milliseconds ms(3); // ok, ms.count() == 3, which is 0.003 seconds</font> | |
336 | <font color="#c80000">// microseconds us = ms; // ok, us.count() == 3000 which is 0.003000 seconds</font> | |
337 | <font color="#c80000">// ++us; // ok, us.count() == 3001 which is 0.003001 seconds</font> | |
338 | <font color="#c80000">// ms = us; // won't compile, might truncate</font> | |
339 | <font color="#c80000">// ms = duration_cast<milliseconds>(us); // ok, ms.count() = 3, truncated a microsecond</font> | |
340 | <font color="#c80000">// </font> | |
341 | <font color="#c80000">// A duration has a single observer: rep count() const; which returns the stored</font> | |
342 | <font color="#c80000">// representation which holds the number of elapsed "ticks".</font> | |
343 | <font color="#c80000">// </font> | |
344 | <font color="#c80000">// A duration supports the following member arithmetic:</font> | |
345 | <font color="#c80000">// </font> | |
346 | <font color="#c80000">// duration operator+() const;</font> | |
347 | <font color="#c80000">// duration operator-() const;</font> | |
348 | <font color="#c80000">// duration& operator++();</font> | |
349 | <font color="#c80000">// duration operator++(int);</font> | |
350 | <font color="#c80000">// duration& operator--();</font> | |
351 | <font color="#c80000">// duration operator--(int);</font> | |
352 | <font color="#c80000">// </font> | |
353 | <font color="#c80000">// duration& operator+=(duration d);</font> | |
354 | <font color="#c80000">// duration& operator-=(duration d);</font> | |
355 | <font color="#c80000">// </font> | |
356 | <font color="#c80000">// duration& operator*=(rep rhs);</font> | |
357 | <font color="#c80000">// duration& operator/=(rep rhs);</font> | |
358 | <font color="#c80000">//</font> | |
359 | <font color="#c80000">// The arithmetic simply manipulates the "tick" count in the obvious way (e.g. operator++</font> | |
360 | <font color="#c80000">// increments the tick count by 1).</font> | |
361 | <font color="#c80000">// </font> | |
362 | <font color="#c80000">// A duration supports the following non-member arithmetic.</font> | |
363 | <font color="#c80000">// Let D1 represent duration<Rep1, Period1> and D2 represent duration<Rep2, Period2>.</font> | |
364 | <font color="#c80000">// </font> | |
365 | <font color="#c80000">// common_type<D1, D2>::type operator+( D1, D2); // returns a duration</font> | |
366 | <font color="#c80000">// common_type<D1, D2>::type operator-( D1, D2); // returns a duration</font> | |
367 | <font color="#c80000">// duration<common_type<D1::rep,Rep2>::type, D1::period> operator*( D1, Rep2); // returns a duration</font> | |
368 | <font color="#c80000">// duration<common_type<D1::rep,Rep2>::type, D1::period> operator*(Rep2, D1); // returns a duration</font> | |
369 | <font color="#c80000">// duration<common_type<D1::rep,Rep2>::type, D1::period> operator/( D1, Rep2); // returns a duration</font> | |
370 | <font color="#c80000">// common_type<D1::rep, D2::rep>::type operator/( D1, D2); // returns a scalar</font> | |
371 | <font color="#c80000">// </font> | |
372 | <font color="#c80000">// A duration D1 is fully equality and less-than comparable with any other duration D2, as</font> | |
373 | <font color="#c80000">// long as common_type<D1::rep, D2::rep> is well defined.</font> | |
374 | <font color="#c80000">// Example:</font> | |
375 | <font color="#c80000">// milliseconds ms(3); // ms.count() == 3, which is 0.003 seconds</font> | |
376 | <font color="#c80000">// microseconds us = ms; // us.count() == 3000 which is 0.003000 seconds</font> | |
377 | <font color="#c80000">// --us; // us.count() == 2999 which is 0.002999 seconds</font> | |
378 | <font color="#c80000">// assert(ms != us); // 3 milliseconds is not equal to 2999 microseconds</font> | |
379 | <font color="#c80000">// assert(ms > us); // 3 milliseconds is greater than 2999 microseconds</font> | |
380 | <font color="#c80000">// ++us; // us.count() == 3000 which is 0.003000 seconds</font> | |
381 | <font color="#c80000">// assert(ms == us); // 3 milliseconds is equal to 3000 microseconds</font> | |
382 | <font color="#c80000">//</font> | |
383 | <font color="#c80000">// Durations based on floating point representations are subject to round off error precisely the</font> | |
384 | <font color="#c80000">// same way their representations are.</font> | |
385 | <font color="#c80000">// </font> | |
386 | <font color="#c80000">// Arithmetic and comparisons among integral-based durations is not subject to truncation error or</font> | |
387 | <font color="#c80000">// round off error. If truncation error would result from the arithmetic (say</font> | |
388 | <font color="#c80000">// by converting a smaller period duration to a larger one) the expression will</font> | |
389 | <font color="#c80000">// not compile (unless duration_cast is used). If one performs arithmetic</font> | |
390 | <font color="#c80000">// involving the duration's representation (such as division), then truncation</font> | |
391 | <font color="#c80000">// will happen implicitly.</font> | |
392 | <font color="#c80000">// </font> | |
393 | <font color="#c80000">// Overflow error may silently happen with a duration. The std-defined durations</font> | |
394 | <font color="#c80000">// have a minimum range of +/- 292 years.</font> | |
395 | <font color="#c80000">// </font> | |
396 | <font color="#c80000">// A duration is a thin wrapper around its representation. sizeof(duration<Rep, Period>) == sizeof(Rep).</font> | |
397 | <font color="#c80000">// </font> | |
398 | <font color="#c80000">// A duration can represent units as small as 10^-18 seconds (attoseconds) and as large as 10^18 seconds</font> | |
399 | <font color="#c80000">// (about 30 billion years). The range of a duration is based on the range of its representation</font> | |
400 | <font color="#c80000">// combined with its period.</font> | |
401 | ||
402 | <font color="#c80000">// The cost of not including the flexibility to represent different "tick periods" in the duration</font> | |
403 | <font color="#c80000">// type would be a great loss of both flexibility, convenience and safety for the client. For example</font> | |
404 | <font color="#c80000">// if had just one duration type which counted nanoseconds (no matter how that count was represented),</font> | |
405 | <font color="#c80000">// then clients could never have the ability to traffic in picoseconds. And the only hope of reaching</font> | |
406 | <font color="#c80000">// beyond a +/- 292 year range with nanoseconds is to increase the number of bits in the representation</font> | |
407 | <font color="#c80000">// (such as a long long). Furthermore, if the client wanted to traffic in units larger than a nanosecond</font> | |
408 | <font color="#c80000">// (e.g. seconds) for convience, they would likely need to set up their own conversion constants and</font> | |
409 | <font color="#c80000">// convert manually.</font> | |
410 | <font color="#c80000">//</font> | |
411 | <font color="#c80000">// If the conversion constants are specified at run time, rather than as compile time integral constants,</font> | |
412 | <font color="#c80000">// then the client suffers a significant performance penalty as for every conversion one will have to</font> | |
413 | <font color="#c80000">// perform both a multiplication and a division. In contrast, when converting among any two units of</font> | |
414 | <font color="#c80000">// the set (hours, minutes, seconds, milliseconds, microseconds, nanoseconds), there need be only a</font> | |
415 | <font color="#c80000">// single multiplication *or* division (never both). This proposal makes every unit conversion as</font> | |
416 | <font color="#c80000">// efficient as if it had been coded by hand (see duration_cast). Furthermore duration_cast encapsulates</font> | |
417 | <font color="#c80000">// all unit conversions within a single uniform-syntax function which is easily used in generic code. There</font> | |
418 | <font color="#c80000">// is no need (or motivation) to set up a "hub-and-spoke" conversion regimen, so that the number of conversion</font> | |
419 | <font color="#c80000">// functions is O(N) rather than O(N^2).</font> | |
420 | ||
421 | template <class Rep, class Period = ratio<1>> | |
422 | requires Rep is an arithmetic type, or a class emulating an arithmetic type, | |
423 | and not an instantiation of duration | |
424 | requires Period is an instantiation of ratio and represents a positive fraction | |
425 | class duration | |
426 | { | |
427 | public: | |
428 | typedef Rep rep; | |
429 | typedef Period period; | |
430 | private: | |
431 | rep rep_; <font color="#c80000">// exposition only</font> | |
432 | public: | |
433 | <font color="#c80000">// construction / destruction</font> | |
434 | duration() = default; | |
435 | template <class Rep2> | |
436 | requires is_convertible<Rep2, rep>::value && | |
437 | (treat_as_floating_point<rep>::value || | |
438 | !treat_as_floating_point<rep>::value && !treat_as_floating_point<Rep2>::value) | |
439 | explicit duration(const Rep2& r); | |
440 | ~duration() = default; | |
441 | ||
442 | <font color="#c80000">// copy semantics</font> | |
443 | duration(const duration&) = default; | |
444 | duration& operator=(const duration&) = default; | |
445 | ||
446 | <font color="#c80000">// conversions</font> | |
447 | template <class Rep2, class Period2> | |
448 | requires Rep2 is explicitly convertible to rep && | |
449 | (treat_as_floating_point<rep>::value || | |
450 | !treat_as_floating_point<Rep2>::value && ratio_divide<Period2, period>::type::den == 1) | |
451 | duration(const duration<Rep2, Period2>& d); | |
452 | ||
453 | <font color="#c80000">// observer</font> | |
454 | ||
455 | rep count() const; | |
456 | ||
457 | <font color="#c80000">// arithmetic</font> | |
458 | ||
459 | duration operator+() const; | |
460 | duration operator-() const; | |
461 | duration& operator++(); | |
462 | duration operator++(int); | |
463 | duration& operator--(); | |
464 | duration operator--(int); | |
465 | ||
466 | duration& operator+=(const duration& d); | |
467 | duration& operator-=(const duration& d); | |
468 | ||
469 | duration& operator*=(const rep& rhs); | |
470 | duration& operator/=(const rep& rhs); | |
471 | ||
472 | <font color="#c80000">// special values</font> | |
473 | ||
474 | static constexpr duration zero(); | |
475 | static constexpr duration min(); | |
476 | static constexpr duration max(); | |
477 | }; | |
478 | ||
479 | <font color="#c80000">// convenience typedefs</font> | |
480 | ||
481 | typedef duration<int_least64_t, nano> nanoseconds; <font color="#c80000">// 10^-9 seconds</font> | |
482 | typedef duration<int_least55_t, micro> microseconds; <font color="#c80000">// 10^-6 seconds</font> | |
483 | typedef duration<int_least45_t, milli> milliseconds; <font color="#c80000">// 10^-3 seconds</font> | |
484 | typedef duration<int_least35_t > seconds; <font color="#c80000">// 1 second</font> | |
485 | typedef duration<int_least29_t, ratio< 60>> minutes; <font color="#c80000">// 60 seconds</font> | |
486 | typedef duration<int_least23_t, ratio<3600>> hours; <font color="#c80000">// 3600 seconds</font> | |
487 | ||
488 | <font color="#c80000">// duration_cast can be used to force a conversion between two durations (assuming</font> | |
489 | <font color="#c80000">// the source representation can be explicitly converted to the target representation).</font> | |
490 | <font color="#c80000">// Not all integral-based durations are implicitly convertible to another (to</font> | |
491 | <font color="#c80000">// avoid accidental truncation error). When truncation error is desired, the client</font> | |
492 | <font color="#c80000">// uses duration_cast to explicitly request the non-exact conversion. When</font> | |
493 | <font color="#c80000">// duration_cast is used to convert between durations which have an implicit conversion,</font> | |
494 | <font color="#c80000">// the behavior and performance of the conversion using duration_cast is identical to</font> | |
495 | <font color="#c80000">// that of the implicit conversion.</font> | |
496 | ||
497 | template <class ToDuration, class Rep, class Period> | |
498 | requires ToDuration is an instantiation of duration | |
499 | ToDuration duration_cast(const duration<Rep, Period>& fd); | |
500 | ||
501 | <font color="#c80000">// Examples:</font> | |
502 | <font color="#c80000">// microseconds us(3500); // 3500 microseconds</font> | |
503 | <font color="#c80000">// milliseconds ms = us; // Does not compile (implicit truncation)</font> | |
504 | <font color="#c80000">// milliseconds ms = duration_cast<milliseconds>(us); // 3 milliseconds (explicit truncation)</font> | |
505 | <font color="#c80000">// us = ms; // 3000 microseconds</font> | |
506 | <font color="#c80000">// us = duration_cast<microseconds>(ms); // 3000 microseconds</font> | |
507 | ||
508 | } <font color="#c80000">// datetime</font> | |
509 | ||
510 | <font color="#c80000">// Given two durations: duration<Rep1, Period1> and duration<Rep2, Period2>, the common_type</font> | |
511 | <font color="#c80000">// of those two durations is a duration with a representation of common_type<Rep1, Rep2>,</font> | |
512 | <font color="#c80000">// and a period which is the "greatest common period" of Period1 and Period2. The GCP</font> | |
513 | <font color="#c80000">// (Greatest Common Period) of Period1 and Period2 is the largest period which will divide</font> | |
514 | <font color="#c80000">// both Period1 and Period2 evenly (and is often equivalent to the minimum of Period1 and</font> | |
515 | <font color="#c80000">// Period2). This can be computed (by the implementation at compile time) by</font> | |
516 | <font color="#c80000">// GCD(Period1::num, Period2::num) / LCM(Period1::den, Period2::den) where GCD is</font> | |
517 | <font color="#c80000">// "Greatest Common Divisor" and LCM is "Least Common Multiple".</font> | |
518 | ||
519 | template <class Rep1, class Period1, class Rep2, class Period2> | |
520 | struct common_type<datetime::duration<Rep1, Period1>, datetime::duration<Rep2, Period2> > | |
521 | { | |
522 | typedef datetime::duration<typename common_type<Rep1, Rep2>::type, | |
523 | ratio<GCD(Period1::num, Period2::num), LCM(Period1::den, Period2::den)>> type; | |
524 | }; | |
525 | ||
526 | <font color="#c80000">// Note: For any two durations D1 and D2, they will both exactly convert to common_type<D1, D2>::type.</font> | |
527 | <font color="#c80000">// common_type<D1, D2>::type will have the largest possible period to make this possible, and</font> | |
528 | <font color="#c80000">// may be the same type as D1 or D2. Examples:</font> | |
529 | <font color="#c80000">// common_type<minutes, microseconds>::type is microseconds.</font> | |
530 | <font color="#c80000">// common_type<milliseconds, microseconds>::type is microseconds.</font> | |
531 | <font color="#c80000">// common_type<nanoseconds, microseconds>::type is nanoseconds.</font> | |
532 | <font color="#c80000">//</font> | |
533 | <font color="#c80000">// A more complex example:</font> | |
534 | <font color="#c80000">// common_type< duration<long, milli>, duration<int, ratio<1,30>> >::type is</font> | |
535 | <font color="#c80000">// duration<long, ratio<1,3000>>. And both duration<long, milli> and </font> | |
536 | <font color="#c80000">// duration<int, ratio<1,30>> will exactly convert to duration<long, ratio<1,3000>>.</font> | |
537 | <font color="#c80000">// The former multitplies its representation by 3L and the latter converts its</font> | |
538 | <font color="#c80000">// representation to long and multiplies that result by 1000L. There exists no</font> | |
539 | <font color="#c80000">// duration with a larger period such that both duration<long, milli> and</font> | |
540 | <font color="#c80000">// duration<int, ratio<1,30>> will exactly convert to it.</font> | |
541 | ||
542 | namespace datetime { | |
543 | ||
544 | template <class Rep1, class Period1, class Rep2, class Period2> | |
545 | bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); | |
546 | template <class Rep1, class Period1, class Rep2, class Period2> | |
547 | bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); | |
548 | template <class Rep1, class Period1, class Rep2, class Period2> | |
549 | bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); | |
550 | template <class Rep1, class Period1, class Rep2, class Period2> | |
551 | bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); | |
552 | template <class Rep1, class Period1, class Rep2, class Period2> | |
553 | bool operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); | |
554 | template <class Rep1, class Period1, class Rep2, class Period2> | |
555 | bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); | |
556 | ||
557 | template <class Rep1, class Period1, class Rep2, class Period2> | |
558 | typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type | |
559 | operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); | |
560 | ||
561 | template <class Rep1, class Period1, class Rep2, class Period2> | |
562 | typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type | |
563 | operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); | |
564 | ||
565 | template <class Rep1, class Period, class Rep2> | |
566 | requires Constructible<Rep1, typename common_type<Rep1, Rep2>::type>::value> && | |
567 | Constructible<Rep2, typename common_type<Rep1, Rep2>::type>::value> | |
568 | duration<typename common_type<Rep1, Rep2>::type, Period> | |
569 | operator*(const duration<Rep, Period>& d, const Rep2& s); | |
570 | ||
571 | template <class Rep1, class Period, class Rep2> | |
572 | requires Constructible<Rep1, typename common_type<Rep1, Rep2>::type>::value> && | |
573 | Constructible<Rep2, typename common_type<Rep1, Rep2>::type>::value> | |
574 | duration<typename common_type<Rep1, Rep2>::type, Period> | |
575 | operator*(const Rep2& s, const duration<Rep, Period>& d); | |
576 | ||
577 | template <class Rep1, class Period, class Rep2> | |
578 | requires Rep2 is not a duration && | |
579 | Constructible<Rep1, typename common_type<Rep1, Rep2>::type>::value> && | |
580 | Constructible<Rep2, typename common_type<Rep1, Rep2>::type>::value> | |
581 | duration<typename common_type<Rep1, Rep2>::type, Period> | |
582 | operator/(const duration<Rep, Period>& d, const Rep2& s); | |
583 | ||
584 | <font color="#c80000">// Note: the above 3 signatures can be approximated with is_convertible if concepts do not</font> | |
585 | <font color="#c80000">// make it into the language. Requiring only *explicit* convertibility between the Rep</font> | |
586 | <font color="#c80000">// types is strongly desired. One way or another, Rep2 must be constrained. Otherwise</font> | |
587 | <font color="#c80000">// the operators are overly generic.</font> | |
588 | ||
589 | template <class Rep1, class Period1, class Rep2, class Period2> | |
590 | typename common_type<Rep1, Rep2>::type | |
591 | operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); | |
592 | ||
593 | <font color="#c80000">// time_point</font> | |
594 | ||
595 | <font color="#c80000">// A time_point represents an epoch plus or minus a duration. The relationship between a time_point</font> | |
596 | <font color="#c80000">// which represents "now" and the time_point's epoch is obtained via a clock. Each time_point is</font> | |
597 | <font color="#c80000">// tied to a specific clock. Thus, for any time_point, one can find the duration between that</font> | |
598 | <font color="#c80000">// point in time and now, and between that point in time, and its epoch.</font> | |
599 | <font color="#c80000">// </font> | |
600 | <font color="#c80000">// A time_point may be default constructed. This time_point represents the epoch. time_point has</font> | |
601 | <font color="#c80000">// default copy semantics.</font> | |
602 | <font color="#c80000">// </font> | |
603 | <font color="#c80000">// time_point may be explicitly constructed by a duration having the same representation and period as</font> | |
604 | <font color="#c80000">// the time_point. Any other duration which is implicitly convertible to the time_point's "native" duration can</font> | |
605 | <font color="#c80000">// also be used to explicitly construct the time_point. The meaning of this construction is identical to</font> | |
606 | <font color="#c80000">// time_point() + d.</font> | |
607 | <font color="#c80000">//</font> | |
608 | <font color="#c80000">// A time_point is implicitly constructible from another time_point if they share the same clock,</font> | |
609 | <font color="#c80000">// and the duration of this time_point is implicitly constructible from the duration of the other</font> | |
610 | <font color="#c80000">// time_point. A time_point constructed in this fashion will compare equal to the source time_point</font> | |
611 | <font color="#c80000">// after the construction.</font> | |
612 | <font color="#c80000">// </font> | |
613 | <font color="#c80000">// A time_point supports the following member arithmetic:</font> | |
614 | <font color="#c80000">// </font> | |
615 | <font color="#c80000">// time_point& operator+=(duration d);</font> | |
616 | <font color="#c80000">// time_point& operator-=(duration d);</font> | |
617 | <font color="#c80000">// </font> | |
618 | <font color="#c80000">// A time_point supports the following non-member arithmetic.</font> | |
619 | <font color="#c80000">// Let T1 represent time_point<Clock, Duration1>,</font> | |
620 | <font color="#c80000">// T2 represent time_point<Clock, Duration2>,</font> | |
621 | <font color="#c80000">// and D represent duration<Rep3, Period3>. Note that T1 and T2 must have the same Clock.</font> | |
622 | <font color="#c80000">// Attempts to interoperate times having different clocks results in a compile time failure.</font> | |
623 | <font color="#c80000">// </font> | |
624 | <font color="#c80000">// T2 operator+(T1, D); // return type is a time_point</font> | |
625 | <font color="#c80000">// T2 operator+( D, T1); // return type is a time_point</font> | |
626 | <font color="#c80000">// T2 operator-(T1, D); // return type is a time_point</font> | |
627 | <font color="#c80000">// D operator-(T1, T2); // return type is a duration</font> | |
628 | <font color="#c80000">// </font> | |
629 | <font color="#c80000">// A time_point T1 is fully equality and less-than comparable with any other time_point T2 which</font> | |
630 | <font color="#c80000">// has the same clock, and for which their durations are comparable.</font> | |
631 | <font color="#c80000">// </font> | |
632 | <font color="#c80000">// Times based on floating point representations are subject to round off error precisely the</font> | |
633 | <font color="#c80000">// same way their representations are.</font> | |
634 | <font color="#c80000">// </font> | |
635 | <font color="#c80000">// Times based on integral representations are not subject to truncation error or round off</font> | |
636 | <font color="#c80000">// error. A compile time error will result if truncation error is possible. Truncation error</font> | |
637 | <font color="#c80000">// is only possible with construction or the member arithmetic (and won't compile). Non-member</font> | |
638 | <font color="#c80000">// arithmetic and comparison is always exact. Overflow error with integral based times remains a</font> | |
639 | <font color="#c80000">// possibility.</font> | |
640 | <font color="#c80000">// </font> | |
641 | <font color="#c80000">// A time_point is a thin wrapper around its representation.</font> | |
642 | <font color="#c80000">// sizeof(time_point<Clock, Duration>) == sizeof(Duration) == sizeof(Duration::rep).</font> | |
643 | <font color="#c80000">// </font> | |
644 | <font color="#c80000">// A time_point can represent units as small as 10^-18 seconds and as large as 10^18 seconds. The range</font> | |
645 | <font color="#c80000">// of a time_point is based on the range of its representation combined with its period.</font> | |
646 | <font color="#c80000">//</font> | |
647 | <font color="#c80000">// Because no two clocks report the exact same time, even clocks which nominally have the same</font> | |
648 | <font color="#c80000">// epoch, are considered by this framework to have different epochs, if only by a few nanoseconds.</font> | |
649 | <font color="#c80000">// Converting time_points from one clock to another will involve synchronization of the clocks,</font> | |
650 | <font color="#c80000">// which can be viewed as a synchronization of their epochs. Such synchronization is clock specific</font> | |
651 | <font color="#c80000">// and beyond the scope of this API. A future API, or a platform specific API, can easily</font> | |
652 | <font color="#c80000">// write such a synchronization API, basing it on this API.</font> | |
653 | ||
654 | <font color="#c80000">// The cost of not including a time_point class is the lack of the ability to safely interact with</font> | |
655 | <font color="#c80000">// the concept of "epoch + duration". Without a separate type, the client is in danger of accidently</font> | |
656 | <font color="#c80000">// writing code that boils down to "epoch1 + duration1" + "epoch2 + duration2". Algebraically this</font> | |
657 | <font color="#c80000">// results in epoch1+epoch2 as a subexpression which is likely to be completely without meaning. What</font> | |
658 | <font color="#c80000">// would it mean to add New Years 1970 to the point in time at which your computer booted up? Or for</font> | |
659 | <font color="#c80000">// that matter, what is the meaning of "New Years 1970" + "New Years 1970"?</font> | |
660 | <font color="#c80000">//</font> | |
661 | <font color="#c80000">// Additionally this would force the duration type to play double duty as a time_point leading to</font> | |
662 | <font color="#c80000">// client confusion. For example POSIX has timespec represent a duration in nanosleep, and yet the</font> | |
663 | <font color="#c80000">// same type is used as a time_point in pthread_cond_timedwait and pthread_mutex_timedlock. The</font> | |
664 | <font color="#c80000">// confusion seems even more likely with a function such as clock_nanosleep where timespec can mean</font> | |
665 | <font color="#c80000">// either a duration or a time_point depending upon another argument to the function.</font> | |
666 | <font color="#c80000">//</font> | |
667 | <font color="#c80000">// In C++ we can easily mitigate such errors by detecting them at compile time. This is done through</font> | |
668 | <font color="#c80000">// the use of distinct types for these distinct concepts (even though both types have identical layout!).</font> | |
669 | ||
670 | template <class Clock, class Duration = typename Clock::duration> | |
671 | requires Duration is an instantiation of duration | |
672 | class time_point | |
673 | { | |
674 | public: | |
675 | typedef Clock clock; | |
676 | typedef Duration duration; | |
677 | typedef typename duration::rep rep; | |
678 | typedef typename duration::period period; | |
679 | private: | |
680 | duration d_; <font color="#c80000">// exposition only</font> | |
681 | ||
682 | public: | |
683 | time_point(); <font color="#c80000">// has value "epoch"</font> | |
684 | explicit time_point(const duration& d); <font color="#c80000">// same as time_point() + d</font> | |
685 | ||
686 | <font color="#c80000">// conversions</font> | |
687 | template <class Duration2> | |
688 | requires Convertible<Duration2, duration> | |
689 | time_point(const time_point<clock, Duration2>& t); | |
690 | ||
691 | <font color="#c80000">// observer</font> | |
692 | ||
693 | duration time_since_epoch() const; | |
694 | ||
695 | <font color="#c80000">// arithmetic</font> | |
696 | ||
697 | time_point& operator+=(const duration& d); | |
698 | time_point& operator-=(const duration& d); | |
699 | ||
700 | <font color="#c80000">// special values</font> | |
701 | ||
702 | static time_point min(); | |
703 | static time_point max(); | |
704 | }; | |
705 | ||
706 | } <font color="#c80000">// datetime</font> | |
707 | ||
708 | template <class Clock, class Duration1, class Duration2> | |
709 | struct common_type<datetime::time_point<Clock, Duration1>, datetime::time_point<Clock, Duration2> > | |
710 | { | |
711 | typedef datetime::time_point<Clock, typename common_type<Duration1, Duration2>::type> type; | |
712 | }; | |
713 | ||
714 | namespace datetime { | |
715 | ||
716 | template <class ToDuration, class Clock, class Duration> | |
717 | time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration>& t); | |
718 | ||
719 | template <class Clock, class Duration1, class Duration2> | |
720 | bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); | |
721 | template <class Clock, class Duration1, class Duration2> | |
722 | bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); | |
723 | template <class Clock, class Duration1, class Duration2> | |
724 | bool operator< (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); | |
725 | template <class Clock, class Duration1, class Duration2> | |
726 | bool operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); | |
727 | template <class Clock, class Duration1, class Duration2> | |
728 | bool operator> (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); | |
729 | template <class Clock, class Duration1, class Duration2> | |
730 | bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); | |
731 | ||
732 | template <class Clock, class Duration1, class Rep2, class Period2> | |
733 | time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> | |
734 | operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs); | |
735 | ||
736 | template <class Rep1, class Period1, class Clock, class Duration2> | |
737 | time_point<Clock, typename common_type<duration<Rep1, Period1>, Duration2>::type> | |
738 | operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs); | |
739 | ||
740 | template <class Clock, class Duration1, class Rep2, class Period2> | |
741 | time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> | |
742 | operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs); | |
743 | ||
744 | template <class Clock, class Duration1, class Duration2> | |
745 | typename common_type<Duration1, Duration2>::type | |
746 | operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); | |
747 | ||
748 | <font color="#c80000">// clocks</font> | |
749 | ||
750 | <font color="#c80000">// A clock specifies a representation, and a period. These specifications are used to</font> | |
751 | <font color="#c80000">// to define a clock's native duration and time_point types. A clock also has a function to get the current</font> | |
752 | <font color="#c80000">// time_point. A clock need not have any state.</font> | |
753 | ||
754 | <font color="#c80000">// The cost of not including separate types for clocks is that there is no better place to</font> | |
755 | <font color="#c80000">// bundle the "native" duration and time_point types for a clock with the functionality to</font> | |
756 | <font color="#c80000">// get the current time_point (what time is it now?). By bundling this information into a</font> | |
757 | <font color="#c80000">// type, the extension to support multiple clocks is both easy and obvious. The ability to</font> | |
758 | <font color="#c80000">// easily support multiple clocks in such a flexible yet simple and efficient manner is</font> | |
759 | <font color="#c80000">// very important. A client might (for example) write code with the clock as a generic</font> | |
760 | <font color="#c80000">// template parameter, and then easily experiment with different timers.</font> | |
761 | ||
762 | class system_clock | |
763 | { | |
764 | public: | |
765 | typedef <unspecified> rep; | |
766 | typedef ratio<unspecified, unspecified> period; | |
767 | typedef datetime::duration<rep, period> duration; | |
768 | typedef datetime::time_point<system_clock> time_point; | |
769 | static const bool is_mononontic = <unspecified>; | |
770 | ||
771 | static time_point now(); | |
772 | ||
773 | <font color="#c80000">// Map to C API</font> | |
774 | static time_t to_time_t (const time_point& t); | |
775 | static time_point from_time_t(time_t t); | |
776 | }; | |
777 | ||
778 | class monotonic_clock <font color="#c80000">// optional</font> | |
779 | { | |
780 | public: | |
781 | typedef <unspecified> rep; | |
782 | typedef ratio<unspecified, unspecified> period; | |
783 | typedef datetime::duration<rep, period> duration; | |
784 | typedef datetime::time_point<monotonic_clock> time_point; | |
785 | static const bool is_mononontic = true; | |
786 | ||
787 | static time_point now(); | |
788 | }; | |
789 | ||
790 | class high_resolution_clock <font color="#c80000">// optional</font> | |
791 | { | |
792 | public: | |
793 | typedef <unspecified> rep; | |
794 | typedef ratio<unspecified, unspecified> period; | |
795 | typedef datetime::duration<rep, period> duration; | |
796 | typedef datetime::time_point<high_resolution_clock> time_point; | |
797 | static const bool is_mononontic = <unspecified>; | |
798 | ||
799 | static time_point now(); | |
800 | }; | |
801 | ||
802 | <font color="#c80000">// Note: These clocks may be three separate types, or typedefs to one or two common types.</font> | |
803 | ||
804 | } <font color="#c80000">// datetime</font> | |
805 | ||
806 | <font color="#c80000">//////////////////////////</font> | |
807 | <font color="#c80000">// Threading interface //</font> | |
808 | <font color="#c80000">//////////////////////////</font> | |
809 | ||
810 | <font color="#c80000">// timed_mutex</font> | |
811 | ||
812 | struct timed_mutex | |
813 | { | |
814 | public: | |
815 | timed_mutex(); | |
816 | ~timed_mutex(); | |
817 | ||
818 | timed_mutex(const timed_mutex&) = delete; | |
819 | timed_mutex& operator=(const timed_mutex&) = delete; | |
820 | ||
821 | void lock(); | |
822 | bool try_lock(); | |
823 | template <class Rep, class Period> | |
824 | bool try_lock_for(const datetime::duration<Rep, Period>& rel_time); | |
825 | template <class Clock, class Duration> | |
826 | bool try_lock_until(const datetime::time_point<Clock, Duration>& abs_time); | |
827 | void unlock(); | |
828 | ||
829 | typedef unspecified native_handle_type; <font color="#c80000">// optional. example: pthread_mutex_t*</font> | |
830 | native_handle_type native_handle(); <font color="#c80000">// optional</font> | |
831 | }; | |
832 | ||
833 | <font color="#c80000">// recursive_timed_mutex</font> | |
834 | ||
835 | struct recursive_timed_mutex | |
836 | { | |
837 | public: | |
838 | recursive_timed_mutex(); | |
839 | ~recursive_timed_mutex(); | |
840 | ||
841 | recursive_timed_mutex(const recursive_timed_mutex&) = delete; | |
842 | recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; | |
843 | ||
844 | void lock(); | |
845 | bool try_lock(); | |
846 | template <class Rep, class Period> | |
847 | bool try_lock_for(const datetime::duration<Rep, Period>& rel_time); | |
848 | template <class Clock, class Duration> | |
849 | bool try_lock_until(const datetime::time_point<Clock, Duration>& abs_time); | |
850 | void unlock(); | |
851 | ||
852 | typedef unspecified native_handle_type; <font color="#c80000">// optional. example: pthread_mutex_t*</font> | |
853 | native_handle_type native_handle(); <font color="#c80000">// optional</font> | |
854 | }; | |
855 | ||
856 | <font color="#c80000">// unique_lock</font> | |
857 | ||
858 | template <class Mutex> | |
859 | class unique_lock | |
860 | { | |
861 | public: | |
862 | typedef Mutex mutex_type; | |
863 | ||
864 | unique_lock(); | |
865 | explicit unique_lock(mutex_type& m); | |
866 | unique_lock(mutex_type& m, defer_lock_t); | |
867 | unique_lock(mutex_type& m, try_to_lock_t); | |
868 | unique_lock(mutex_type& m, adopt_lock_t); | |
869 | template <class Rep, class Period> | |
870 | unique_lock(mutex_type& m, const datetime::duration<Rep, Period>& rel_t); | |
871 | template <class Clock, class Duration> | |
872 | unique_lock(mutex_type& m, const datetime::time_point<Clock, Duration>& abs_time); | |
873 | ~unique_lock(); | |
874 | ||
875 | unique_lock(unique_lock const&) = delete; | |
876 | unique_lock& operator=(unique_lock const&) = delete; | |
877 | ||
878 | unique_lock(unique_lock&& u); | |
879 | unique_lock& operator=(unique_lock&& u); | |
880 | ||
881 | void lock(); | |
882 | bool try_lock(); | |
883 | template <class Rep, class Period> | |
884 | bool try_lock_for(const datetime::duration<Rep, Period>& rel_t); | |
885 | template <class Clock, class Duration> | |
886 | bool try_lock_until(const datetime::time_point<Clock, Duration>& abs_time); | |
887 | void unlock(); | |
888 | ||
889 | bool owns_lock() const; | |
890 | operator unspecified-bool-type () const; | |
891 | mutex_type* mutex() const; | |
892 | ||
893 | void swap(unique_lock&& u); | |
894 | mutex_type* release(); | |
895 | }; | |
896 | ||
897 | <font color="#c80000">// condition_variable</font> | |
898 | ||
899 | class condition_variable | |
900 | { | |
901 | public: | |
902 | ||
903 | condition_variable(); | |
904 | ~condition_variable(); | |
905 | ||
906 | condition_variable(const condition_variable&) = delete; | |
907 | condition_variable& operator=(const condition_variable&) = delete; | |
908 | ||
909 | void notify_one(); | |
910 | void notify_all(); | |
911 | ||
912 | void wait(unique_lock<mutex>& lock); | |
913 | template <class Predicate> | |
914 | void wait(unique_lock<mutex>& lock, Predicate pred); | |
915 | ||
916 | template <class Clock, class Duration> | |
917 | bool wait_until(unique_lock<mutex>& lock, | |
918 | const datetime::time_point<Clock, Duration>& abs_time); | |
919 | template <class Clock, class Duration, class Predicate> | |
920 | bool wait_until(unique_lock<mutex>& lock, | |
921 | const datetime::time_point<Clock, Duration>& abs_time, | |
922 | Predicate pred); | |
923 | ||
924 | template <class Rep, class Period> | |
925 | bool wait_for(unique_lock<mutex>& lock, const datetime::duration<Rep, Period>& rel_time); | |
926 | template <class Rep, class Period, class Predicate> | |
927 | bool wait_for(unique_lock<mutex>& lock, const datetime::duration<Rep, Period>& rel_time, | |
928 | Predicate pred); | |
929 | ||
930 | typedef pthread_cond_t* native_handle_type; | |
931 | native_handle_type native_handle(); | |
932 | }; | |
933 | ||
934 | <font color="#c80000">// condition_variable_any</font> | |
935 | ||
936 | class condition_variable_any | |
937 | { | |
938 | public: | |
939 | ||
940 | condition_variable_any(); | |
941 | ~condition_variable_any(); | |
942 | ||
943 | condition_variable_any(const condition_variable_any&) = delete; | |
944 | condition_variable_any& operator=(const condition_variable_any&) = delete; | |
945 | ||
946 | void notify_one(); | |
947 | void notify_all(); | |
948 | ||
949 | template <class Lock> | |
950 | void wait(Lock& lock); | |
951 | template <class Lock, class Predicate> | |
952 | void wait(Lock& lock, Predicate pred); | |
953 | ||
954 | template <class Lock, class Clock, class Duration> | |
955 | bool wait_until(Lock& lock, const datetime::time_point<Clock, Duration>& abs_time); | |
956 | template <class Lock, class Clock, class Duration, class Predicate> | |
957 | bool wait_until(Lock& lock, const datetime::time_point<Clock, Duration>& abs_time, | |
958 | Predicate pred); | |
959 | ||
960 | template <class Lock, class Rep, class Period> | |
961 | bool wait_for(Lock& lock, const datetime::duration<Rep, Period>& rel_time); | |
962 | template <class Lock, class Rep, class Period, class Predicate> | |
963 | bool wait_for(Lock& lock, const datetime::duration<Rep, Period>& rel_time, Predicate pred); | |
964 | }; | |
965 | ||
966 | <font color="#c80000">// sleep</font> | |
967 | ||
968 | namespace this_thread | |
969 | { | |
970 | ||
971 | template <class Rep, class Period> | |
972 | void sleep_for(const datetime::duration<Rep, Period>& rel_time); | |
973 | ||
974 | template <class Clock, class Duration> | |
975 | void sleep_until(const datetime::time_point<Clock, Duration>& abs_time); | |
976 | ||
977 | } <font color="#c80000">// this_thread</font> | |
978 | ||
979 | } <font color="#c80000">// std</font> | |
980 | ||
981 | */</font> | |
982 | ||
983 | #include <ctime> | |
984 | #include <climits> | |
985 | #include <inttypes.h> | |
986 | #include <limits> | |
987 | #include "type_traits" | |
988 | ||
989 | #define decltype __typeof__ | |
990 | ||
991 | namespace std | |
992 | { | |
993 | ||
994 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
995 | <font color="#c80000">////////////////////// common_type ///////////////////////</font> | |
996 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
997 | ||
998 | #define VARIADIC_COMMON_TYPE 0 | |
999 | ||
1000 | #if VARIADIC_COMMON_TYPE == 0 | |
1001 | ||
1002 | template <class T, class U> | |
1003 | struct common_type | |
1004 | { | |
1005 | private: | |
1006 | static T t(); | |
1007 | static U u(); | |
1008 | public: | |
1009 | typedef decltype(true ? t() : u()) type; | |
1010 | }; | |
1011 | ||
1012 | #else | |
1013 | ||
1014 | template <class ...T> struct common_type; | |
1015 | ||
1016 | template <class T> | |
1017 | struct common_type<T> | |
1018 | { | |
1019 | typedef T type; | |
1020 | }; | |
1021 | ||
1022 | template <class T, class U> | |
1023 | struct common_type<T, U> | |
1024 | { | |
1025 | private: | |
1026 | static T t(); | |
1027 | static U u(); | |
1028 | public: | |
1029 | typedef decltype(true ? t() : u()) type; | |
1030 | }; | |
1031 | ||
1032 | template <class T, class U, class ...V> | |
1033 | struct common_type<T, U, V...> | |
1034 | { | |
1035 | typedef typename common_type<typename common_type<T, U>::type, V...>::type type; | |
1036 | }; | |
1037 | ||
1038 | #endif | |
1039 | ||
1040 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
1041 | <font color="#c80000">/////////////////////// ratio ////////////////////////////</font> | |
1042 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
1043 | ||
1044 | <font color="#c80000">// __static_gcd</font> | |
1045 | ||
1046 | template <intmax_t X, intmax_t Y> | |
1047 | struct __static_gcd | |
1048 | { | |
1049 | static const intmax_t value = __static_gcd<Y, X % Y>::value; | |
1050 | }; | |
1051 | ||
1052 | template <intmax_t X> | |
1053 | struct __static_gcd<X, 0> | |
1054 | { | |
1055 | static const intmax_t value = X; | |
1056 | }; | |
1057 | ||
1058 | <font color="#c80000">// __static_lcm</font> | |
1059 | ||
1060 | template <intmax_t X, intmax_t Y> | |
1061 | struct __static_lcm | |
1062 | { | |
1063 | static const intmax_t value = X / __static_gcd<X, Y>::value * Y; | |
1064 | }; | |
1065 | ||
1066 | template <intmax_t X> | |
1067 | struct __static_abs | |
1068 | { | |
1069 | static const intmax_t value = X < 0 ? -X : X; | |
1070 | }; | |
1071 | ||
1072 | template <intmax_t X> | |
1073 | struct __static_sign | |
1074 | { | |
1075 | static const intmax_t value = X == 0 ? 0 : (X < 0 ? -1 : 1); | |
1076 | }; | |
1077 | ||
1078 | template <intmax_t X, intmax_t Y, intmax_t = __static_sign<Y>::value> | |
1079 | class __ll_add; | |
1080 | ||
1081 | template <intmax_t X, intmax_t Y> | |
1082 | class __ll_add<X, Y, 1> | |
1083 | { | |
1084 | static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; | |
1085 | static const intmax_t max = -min; | |
1086 | ||
1087 | static char test[X <= max - Y]; | |
1088 | <font color="#c80000">// static_assert(X <= max - Y, "overflow in __ll_add");</font> | |
1089 | public: | |
1090 | static const intmax_t value = X + Y; | |
1091 | }; | |
1092 | ||
1093 | template <intmax_t X, intmax_t Y> | |
1094 | class __ll_add<X, Y, 0> | |
1095 | { | |
1096 | public: | |
1097 | static const intmax_t value = X; | |
1098 | }; | |
1099 | ||
1100 | template <intmax_t X, intmax_t Y> | |
1101 | class __ll_add<X, Y, -1> | |
1102 | { | |
1103 | static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; | |
1104 | static const intmax_t max = -min; | |
1105 | ||
1106 | static char test[min - Y <= X]; | |
1107 | <font color="#c80000">// static_assert(min - Y <= X, "overflow in __ll_add");</font> | |
1108 | public: | |
1109 | static const intmax_t value = X + Y; | |
1110 | }; | |
1111 | ||
1112 | template <intmax_t X, intmax_t Y, intmax_t = __static_sign<Y>::value> | |
1113 | class __ll_sub; | |
1114 | ||
1115 | template <intmax_t X, intmax_t Y> | |
1116 | class __ll_sub<X, Y, 1> | |
1117 | { | |
1118 | static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; | |
1119 | static const intmax_t max = -min; | |
1120 | ||
1121 | static char test[min + Y <= X]; | |
1122 | <font color="#c80000">// static_assert(min + Y <= X, "overflow in __ll_sub");</font> | |
1123 | public: | |
1124 | static const intmax_t value = X - Y; | |
1125 | }; | |
1126 | ||
1127 | template <intmax_t X, intmax_t Y> | |
1128 | class __ll_sub<X, Y, 0> | |
1129 | { | |
1130 | public: | |
1131 | static const intmax_t value = X; | |
1132 | }; | |
1133 | ||
1134 | template <intmax_t X, intmax_t Y> | |
1135 | class __ll_sub<X, Y, -1> | |
1136 | { | |
1137 | static const intmax_t min = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1; | |
1138 | static const intmax_t max = -min; | |
1139 | ||
1140 | static char test[X <= max + Y]; | |
1141 | <font color="#c80000">// static_assert(X <= max + Y, "overflow in __ll_sub");</font> | |
1142 | public: | |
1143 | static const intmax_t value = X - Y; | |
1144 | }; | |
1145 | ||
1146 | template <intmax_t X, intmax_t Y> | |
1147 | class __ll_mul | |
1148 | { | |
1149 | static const intmax_t nan = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)); | |
1150 | static const intmax_t min = nan + 1; | |
1151 | static const intmax_t max = -min; | |
1152 | static const intmax_t __a_x = __static_abs<X>::value; | |
1153 | static const intmax_t __a_y = __static_abs<Y>::value; | |
1154 | ||
1155 | static char test1[X != nan]; | |
1156 | static char test2[Y != nan]; | |
1157 | static char test[__a_x <= max / __a_y]; | |
1158 | <font color="#c80000">// static_assert(X != nan && Y != nan && __a_x <= max / __a_y, "overflow in __ll_mul");</font> | |
1159 | public: | |
1160 | static const intmax_t value = X * Y; | |
1161 | }; | |
1162 | ||
1163 | template <intmax_t Y> | |
1164 | class __ll_mul<0, Y> | |
1165 | { | |
1166 | public: | |
1167 | static const intmax_t value = 0; | |
1168 | }; | |
1169 | ||
1170 | template <intmax_t X> | |
1171 | class __ll_mul<X, 0> | |
1172 | { | |
1173 | public: | |
1174 | static const intmax_t value = 0; | |
1175 | }; | |
1176 | ||
1177 | template <> | |
1178 | class __ll_mul<0, 0> | |
1179 | { | |
1180 | public: | |
1181 | static const intmax_t value = 0; | |
1182 | }; | |
1183 | ||
1184 | <font color="#c80000">// Not actually used but left here in case needed in future maintenance</font> | |
1185 | template <intmax_t X, intmax_t Y> | |
1186 | class __ll_div | |
1187 | { | |
1188 | static const intmax_t nan = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)); | |
1189 | static const intmax_t min = nan + 1; | |
1190 | static const intmax_t max = -min; | |
1191 | ||
1192 | static char test1[X != nan]; | |
1193 | static char test2[Y != nan]; | |
1194 | static char test3[Y != 0]; | |
1195 | <font color="#c80000">// static_assert(X != nan && Y != nan && Y != 0, "overflow in __ll_div");</font> | |
1196 | public: | |
1197 | static const intmax_t value = X / Y; | |
1198 | }; | |
1199 | ||
1200 | template <intmax_t N, intmax_t D = 1> | |
1201 | class ratio | |
1202 | { | |
1203 | static char test1[__static_abs<N>::value >= 0]; | |
1204 | static char test2[__static_abs<D>::value > 0]; | |
1205 | <font color="#c80000">// static_assert(__static_abs<N>::value >= 0, "ratio numerator is out of range");</font> | |
1206 | <font color="#c80000">// static_assert(D != 0, "ratio divide by 0");</font> | |
1207 | <font color="#c80000">// static_assert(__static_abs<D>::value > 0, "ratio denominator is out of range");</font> | |
1208 | static const intmax_t __na = __static_abs<N>::value; | |
1209 | static const intmax_t __da = __static_abs<D>::value; | |
1210 | static const intmax_t __s = __static_sign<N>::value * __static_sign<D>::value; | |
1211 | static const intmax_t __gcd = __static_gcd<__na, __da>::value; | |
1212 | public: | |
1213 | static const intmax_t num = __s * __na / __gcd; | |
1214 | static const intmax_t den = __da / __gcd; | |
1215 | }; | |
1216 | ||
1217 | template <class T> struct ___is_ratio : tmp::false_type {}; | |
1218 | template <intmax_t N, intmax_t D> struct ___is_ratio<ratio<N, D> > : tmp::true_type {}; | |
1219 | template <class T> struct __is_ratio : ___is_ratio<typename tmp::remove_cv<T>::type> {}; | |
1220 | ||
1221 | typedef ratio<1LL, 1000000000000000000LL> atto; | |
1222 | typedef ratio<1LL, 1000000000000000LL> femto; | |
1223 | typedef ratio<1LL, 1000000000000LL> pico; | |
1224 | typedef ratio<1LL, 1000000000LL> nano; | |
1225 | typedef ratio<1LL, 1000000LL> micro; | |
1226 | typedef ratio<1LL, 1000LL> milli; | |
1227 | typedef ratio<1LL, 100LL> centi; | |
1228 | typedef ratio<1LL, 10LL> deci; | |
1229 | typedef ratio< 10LL, 1LL> deca; | |
1230 | typedef ratio< 100LL, 1LL> hecto; | |
1231 | typedef ratio< 1000LL, 1LL> kilo; | |
1232 | typedef ratio< 1000000LL, 1LL> mega; | |
1233 | typedef ratio< 1000000000LL, 1LL> giga; | |
1234 | typedef ratio< 1000000000000LL, 1LL> tera; | |
1235 | typedef ratio< 1000000000000000LL, 1LL> peta; | |
1236 | typedef ratio<1000000000000000000LL, 1LL> exa; | |
1237 | ||
1238 | template <class R1, class R2> | |
1239 | struct ratio_add | |
1240 | { | |
1241 | typedef ratio<__ll_add<__ll_mul<R1::num, R2::den>::value, | |
1242 | __ll_mul<R1::den, R2::num>::value>::value, | |
1243 | __ll_mul<R1::den, R2::den>::value> type; | |
1244 | }; | |
1245 | ||
1246 | template <class R1, class R2> | |
1247 | struct ratio_subtract | |
1248 | { | |
1249 | typedef ratio<__ll_sub<__ll_mul<R1::num, R2::den>::value, | |
1250 | __ll_mul<R1::den, R2::num>::value>::value, | |
1251 | __ll_mul<R1::den, R2::den>::value> type; | |
1252 | }; | |
1253 | ||
1254 | template <class R1, class R2> | |
1255 | struct ratio_multiply | |
1256 | { | |
1257 | typedef ratio<__ll_mul<R1::num, R2::num>::value, __ll_mul<R1::den, R2::den>::value> type; | |
1258 | }; | |
1259 | ||
1260 | template <class R1, class R2> | |
1261 | struct ratio_divide | |
1262 | { | |
1263 | typedef ratio<__ll_mul<R1::num, R2::den>::value, __ll_mul<R1::den, R2::num>::value> type; | |
1264 | }; | |
1265 | ||
1266 | <font color="#c80000">// ratio_equal</font> | |
1267 | ||
1268 | template <class R1, class R2> | |
1269 | struct ratio_equal | |
1270 | : public tmp::integral_constant<bool, R1::num == R2::num && R1::den == R2::den> {}; | |
1271 | ||
1272 | template <class R1, class R2> | |
1273 | struct ratio_not_equal | |
1274 | : public tmp::integral_constant<bool, !ratio_equal<R1, R2>::value> {}; | |
1275 | ||
1276 | <font color="#c80000">// ratio_less</font> | |
1277 | ||
1278 | <font color="#c80000">// Protect against overflow, and still get the right answer as much as possible.</font> | |
1279 | <font color="#c80000">// This just demonstrates for fun how far you can push things without hitting</font> | |
1280 | <font color="#c80000">// overflow. The obvious and simple implementation is conforming.</font> | |
1281 | ||
1282 | template <class R1, class R2, bool ok1, bool ok2> | |
1283 | struct __ratio_less3 <font color="#c80000">// true, true and false, false</font> | |
1284 | { | |
1285 | static const bool value = __ll_mul<R1::num, R2::den>::value < __ll_mul<R2::num, R1::den>::value; | |
1286 | }; | |
1287 | ||
1288 | template <class R1, class R2> | |
1289 | struct __ratio_less3<R1, R2, true, false> | |
1290 | { | |
1291 | static const bool value = true; | |
1292 | }; | |
1293 | ||
1294 | template <class R1, class R2> | |
1295 | struct __ratio_less3<R1, R2, false, true> | |
1296 | { | |
1297 | static const bool value = false; | |
1298 | }; | |
1299 | ||
1300 | template <class R1, class R2, bool = R1::num < R1::den == R2::num < R2::den> | |
1301 | struct __ratio_less2 <font color="#c80000">// N1 < D1 == N2 < D2</font> | |
1302 | { | |
1303 | static const intmax_t max = -((1LL << (sizeof(intmax_t) * CHAR_BIT - 1)) + 1); | |
1304 | static const bool ok1 = R1::num <= max / R2::den; | |
1305 | static const bool ok2 = R2::num <= max / R1::den; | |
1306 | static const bool value = __ratio_less3<R1, R2, ok1, ok2>::value; | |
1307 | }; | |
1308 | ||
1309 | template <class R1, class R2> | |
1310 | struct __ratio_less2<R1, R2, false> <font color="#c80000">// N1 < D1 != N2 < D2</font> | |
1311 | { | |
1312 | static const bool value = R1::num < R1::den; | |
1313 | }; | |
1314 | ||
1315 | template <class R1, class R2, bool = R1::num < R1::den == R2::num < R2::den> | |
1316 | struct __ratio_less1 <font color="#c80000">// N1 < D1 == N2 < D2</font> | |
1317 | { | |
1318 | static const bool value = __ratio_less2<ratio<R1::num, R2::num>, ratio<R1::den, R2::den> >::value; | |
1319 | }; | |
1320 | ||
1321 | template <class R1, class R2> | |
1322 | struct __ratio_less1<R1, R2, false> <font color="#c80000">// N1 < D1 != N2 < D2</font> | |
1323 | { | |
1324 | static const bool value = R1::num < R1::den; | |
1325 | }; | |
1326 | ||
1327 | template <class R1, class R2, intmax_t S1 = __static_sign<R1::num>::value, | |
1328 | intmax_t S2 = __static_sign<R2::num>::value> | |
1329 | struct __ratio_less | |
1330 | { | |
1331 | static const bool value = S1 < S2; | |
1332 | }; | |
1333 | ||
1334 | template <class R1, class R2> | |
1335 | struct __ratio_less<R1, R2, 1LL, 1LL> | |
1336 | { | |
1337 | static const bool value = __ratio_less1<R1, R2>::value; | |
1338 | }; | |
1339 | ||
1340 | template <class R1, class R2> | |
1341 | struct __ratio_less<R1, R2, -1LL, -1LL> | |
1342 | { | |
1343 | static const bool value = __ratio_less1<ratio<-R2::num, R2::den>, ratio<-R1::num, R1::den> >::value; | |
1344 | }; | |
1345 | ||
1346 | template <class R1, class R2> | |
1347 | struct ratio_less | |
1348 | : public tmp::integral_constant<bool, __ratio_less<R1, R2>::value> {}; | |
1349 | ||
1350 | template <class R1, class R2> | |
1351 | struct ratio_less_equal | |
1352 | : public tmp::integral_constant<bool, !ratio_less<R2, R1>::value> {}; | |
1353 | ||
1354 | template <class R1, class R2> | |
1355 | struct ratio_greater | |
1356 | : public tmp::integral_constant<bool, ratio_less<R2, R1>::value> {}; | |
1357 | ||
1358 | template <class R1, class R2> | |
1359 | struct ratio_greater_equal | |
1360 | : public tmp::integral_constant<bool, !ratio_less<R1, R2>::value> {}; | |
1361 | ||
1362 | template <class R1, class R2> | |
1363 | struct __ratio_gcd | |
1364 | { | |
1365 | typedef ratio<__static_gcd<R1::num, R2::num>::value, | |
1366 | __static_lcm<R1::den, R2::den>::value> type; | |
1367 | }; | |
1368 | ||
1369 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
1370 | <font color="#c80000">////////////////////// duration //////////////////////////</font> | |
1371 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
1372 | ||
1373 | namespace datetime | |
1374 | { | |
1375 | ||
1376 | template <class RepType, class Period = ratio<1> > class duration; | |
1377 | ||
1378 | template <class T> struct ___is_duration : tmp::false_type {}; | |
1379 | template <class Rep, class Period> struct ___is_duration<duration<Rep, Period> > : tmp::true_type {}; | |
1380 | template <class T> struct __is_duration : ___is_duration<typename tmp::remove_cv<T>::type> {}; | |
1381 | ||
1382 | <font color="#c80000">// duration_cast</font> | |
1383 | ||
1384 | <font color="#c80000">// duration_cast is the heart of this whole prototype. It can convert any</font> | |
1385 | <font color="#c80000">// duration to any other. It is also (implicitly) used in converting</font> | |
1386 | <font color="#c80000">// time_points. The conversion is always exact if possible. And it is</font> | |
1387 | <font color="#c80000">// always as efficient as hand written code. If different representations</font> | |
1388 | <font color="#c80000">// are involved, care is taken to never require implicit conversions.</font> | |
1389 | <font color="#c80000">// Instead static_cast is used explicitly for every required conversion.</font> | |
1390 | <font color="#c80000">// If there are a mixture of integral and floating point representations,</font> | |
1391 | <font color="#c80000">// the use of common_type ensures that the most logical "intermediate"</font> | |
1392 | <font color="#c80000">// representation is used.</font> | |
1393 | template <class FromDuration, class ToDuration, | |
1394 | class Period = typename ratio_divide<typename FromDuration::period, typename ToDuration::period>::type, | |
1395 | bool = Period::num == 1, | |
1396 | bool = Period::den == 1> | |
1397 | struct __duration_cast; | |
1398 | ||
1399 | <font color="#c80000">// When the two periods are the same, all that is left to do is static_cast from</font> | |
1400 | <font color="#c80000">// the source representation to the target representation (which may be a no-op).</font> | |
1401 | <font color="#c80000">// This conversion is always exact as long as the static_cast from the source</font> | |
1402 | <font color="#c80000">// representation to the destination representation is exact.</font> | |
1403 | template <class FromDuration, class ToDuration, class Period> | |
1404 | struct __duration_cast<FromDuration, ToDuration, Period, true, true> | |
1405 | { | |
1406 | ToDuration operator()(const FromDuration& fd) const | |
1407 | { | |
1408 | return ToDuration(static_cast<typename ToDuration::rep>(fd.count())); | |
1409 | } | |
1410 | }; | |
1411 | ||
1412 | <font color="#c80000">// When the numerator of FromPeriod / ToPeriod is 1, then all we need to do is</font> | |
1413 | <font color="#c80000">// divide by the denominator of FromPeriod / ToPeriod. The common_type of</font> | |
1414 | <font color="#c80000">// the two representations is used for the intermediate computation before</font> | |
1415 | <font color="#c80000">// static_cast'ing to the destination.</font> | |
1416 | <font color="#c80000">// This conversion is generally not exact because of the division (but could be</font> | |
1417 | <font color="#c80000">// if you get lucky on the run time value of fd.count()).</font> | |
1418 | template <class FromDuration, class ToDuration, class Period> | |
1419 | struct __duration_cast<FromDuration, ToDuration, Period, true, false> | |
1420 | { | |
1421 | ToDuration operator()(const FromDuration& fd) const | |
1422 | { | |
1423 | #if VARIADIC_COMMON_TYPE == 0 | |
1424 | typedef typename common_type< | |
1425 | typename common_type<typename ToDuration::rep, typename FromDuration::rep>::type, | |
1426 | intmax_t>::type C; | |
1427 | #else | |
1428 | typedef typename common_type<typename ToDuration::rep, typename FromDuration::rep, intmax_t>::type C; | |
1429 | #endif | |
1430 | return ToDuration(static_cast<typename ToDuration::rep>( | |
1431 | static_cast<C>(fd.count()) / static_cast<C>(Period::den))); | |
1432 | } | |
1433 | }; | |
1434 | ||
1435 | <font color="#c80000">// When the denomenator of FromPeriod / ToPeriod is 1, then all we need to do is</font> | |
1436 | <font color="#c80000">// multiply by the numerator of FromPeriod / ToPeriod. The common_type of</font> | |
1437 | <font color="#c80000">// the two representations is used for the intermediate computation before</font> | |
1438 | <font color="#c80000">// static_cast'ing to the destination.</font> | |
1439 | <font color="#c80000">// This conversion is always exact as long as the static_cast's involved are exact.</font> | |
1440 | template <class FromDuration, class ToDuration, class Period> | |
1441 | struct __duration_cast<FromDuration, ToDuration, Period, false, true> | |
1442 | { | |
1443 | ToDuration operator()(const FromDuration& fd) const | |
1444 | { | |
1445 | #if VARIADIC_COMMON_TYPE == 0 | |
1446 | typedef typename common_type< | |
1447 | typename common_type<typename ToDuration::rep, typename FromDuration::rep>::type, | |
1448 | intmax_t>::type C; | |
1449 | #else | |
1450 | typedef typename common_type<typename ToDuration::rep, typename FromDuration::rep, intmax_t>::type C; | |
1451 | #endif | |
1452 | return ToDuration(static_cast<typename ToDuration::rep>( | |
1453 | static_cast<C>(fd.count()) * static_cast<C>(Period::num))); | |
1454 | } | |
1455 | }; | |
1456 | ||
1457 | <font color="#c80000">// When neither the numerator or denominator of FromPeriod / ToPeriod is 1, then we need to</font> | |
1458 | <font color="#c80000">// multiply by the numerator and divide by the denominator of FromPeriod / ToPeriod. The</font> | |
1459 | <font color="#c80000">// common_type of the two representations is used for the intermediate computation before</font> | |
1460 | <font color="#c80000">// static_cast'ing to the destination.</font> | |
1461 | <font color="#c80000">// This conversion is generally not exact because of the division (but could be</font> | |
1462 | <font color="#c80000">// if you get lucky on the run time value of fd.count()).</font> | |
1463 | template <class FromDuration, class ToDuration, class Period> | |
1464 | struct __duration_cast<FromDuration, ToDuration, Period, false, false> | |
1465 | { | |
1466 | ToDuration operator()(const FromDuration& fd) const | |
1467 | { | |
1468 | #if VARIADIC_COMMON_TYPE == 0 | |
1469 | typedef typename common_type< | |
1470 | typename common_type<typename ToDuration::rep, typename FromDuration::rep>::type, | |
1471 | intmax_t>::type C; | |
1472 | #else | |
1473 | typedef typename common_type<typename ToDuration::rep, typename FromDuration::rep, intmax_t>::type C; | |
1474 | #endif | |
1475 | return ToDuration(static_cast<typename ToDuration::rep>( | |
1476 | static_cast<C>(fd.count()) * static_cast<C>(Period::num) / static_cast<C>(Period::den))); | |
1477 | } | |
1478 | }; | |
1479 | ||
1480 | <font color="#c80000">// Compile-time select the most efficient algorithm for the conversion...</font> | |
1481 | template <class ToDuration, class Rep, class Period> | |
1482 | inline | |
1483 | typename tmp::enable_if | |
1484 | < | |
1485 | __is_duration<ToDuration>::value, | |
1486 | ToDuration | |
1487 | >::type | |
1488 | duration_cast(const duration<Rep, Period>& fd) | |
1489 | { | |
1490 | return __duration_cast<duration<Rep, Period>, ToDuration>()(fd); | |
1491 | } | |
1492 | ||
1493 | <font color="#c80000">// Support bidirectional (non-exact) conversions for floating point rep types</font> | |
1494 | <font color="#c80000">// (or user defined rep types which specialize treat_as_floating_point).</font> | |
1495 | template <class Rep> struct treat_as_floating_point : tmp::is_floating_point<Rep> {}; | |
1496 | ||
1497 | template <class Rep> | |
1498 | struct duration_values | |
1499 | { | |
1500 | static Rep __min_imp(tmp::false_type) {return -max();} | |
1501 | static Rep __min_imp(tmp::true_type) {return zero();} | |
1502 | public: | |
1503 | static Rep zero() {return Rep(0);} | |
1504 | static Rep max() {return numeric_limits<Rep>::max();} | |
1505 | static Rep min() {return __min_imp(tmp::is_unsigned<Rep>());} | |
1506 | }; | |
1507 | ||
1508 | <font color="#c80000">// duration</font> | |
1509 | ||
1510 | template <class Rep, class Period> | |
1511 | class duration | |
1512 | { | |
1513 | static char test0[!__is_duration<Rep>::value]; | |
1514 | <font color="#c80000">// static_assert(!__is_duration<Rep>::value, "A duration representation can not be a duration");</font> | |
1515 | static char test1[__is_ratio<Period>::value]; | |
1516 | <font color="#c80000">// static_assert(__is_ratio<Period>::value, "Second template parameter of duration must be a std::ratio");</font> | |
1517 | static char test2[Period::num > 0]; | |
1518 | <font color="#c80000">// static_assert(Period::num > 0, "duration period must be positive");</font> | |
1519 | public: | |
1520 | typedef Rep rep; | |
1521 | typedef Period period; | |
1522 | private: | |
1523 | rep rep_; | |
1524 | public: | |
1525 | ||
1526 | duration() {} <font color="#c80000">// = default;</font> | |
1527 | template <class Rep2> | |
1528 | explicit duration(const Rep2& r, | |
1529 | typename tmp::enable_if | |
1530 | < | |
1531 | tmp::is_convertible<Rep2, rep>::value && | |
1532 | (treat_as_floating_point<rep>::value || | |
1533 | !treat_as_floating_point<rep>::value && !treat_as_floating_point<Rep2>::value) | |
1534 | >::type* = 0) | |
1535 | : rep_(r) {} | |
1536 | ||
1537 | <font color="#c80000">// conversions</font> | |
1538 | template <class Rep2, class Period2> | |
1539 | duration(const duration<Rep2, Period2>& d, | |
1540 | typename tmp::enable_if | |
1541 | < | |
1542 | treat_as_floating_point<rep>::value || | |
1543 | (ratio_divide<Period2, period>::type::den == 1 && !treat_as_floating_point<Rep2>::value) | |
1544 | >::type* = 0) | |
1545 | : rep_(duration_cast<duration>(d).count()) {} | |
1546 | ||
1547 | <font color="#c80000">// observer</font> | |
1548 | ||
1549 | rep count() const {return rep_;} | |
1550 | ||
1551 | <font color="#c80000">// arithmetic</font> | |
1552 | ||
1553 | duration operator+() const {return *this;} | |
1554 | duration operator-() const {return duration(-rep_);} | |
1555 | duration& operator++() {++rep_; return *this;} | |
1556 | duration operator++(int) {return duration(rep_++);} | |
1557 | duration& operator--() {--rep_; return *this;} | |
1558 | duration operator--(int) {return duration(rep_--);} | |
1559 | ||
1560 | duration& operator+=(const duration& d) {rep_ += d.count(); return *this;} | |
1561 | duration& operator-=(const duration& d) {rep_ -= d.count(); return *this;} | |
1562 | ||
1563 | duration& operator*=(const rep& rhs) {rep_ *= rhs; return *this;} | |
1564 | duration& operator/=(const rep& rhs) {rep_ /= rhs; return *this;} | |
1565 | ||
1566 | <font color="#c80000">// special values</font> | |
1567 | ||
1568 | static duration zero() {return duration(duration_values<rep>::zero());} | |
1569 | static duration min() {return duration(duration_values<rep>::min());} | |
1570 | static duration max() {return duration(duration_values<rep>::max());} | |
1571 | }; | |
1572 | ||
1573 | typedef duration<long long, nano> nanoseconds; | |
1574 | typedef duration<long long, micro> microseconds; | |
1575 | typedef duration<long long, milli> milliseconds; | |
1576 | typedef duration<long long > seconds; | |
1577 | typedef duration< long, ratio< 60> > minutes; | |
1578 | typedef duration< long, ratio<3600> > hours; | |
1579 | ||
1580 | } <font color="#c80000">// datetime</font> | |
1581 | ||
1582 | template <class Rep1, class Period1, class Rep2, class Period2> | |
1583 | struct common_type<datetime::duration<Rep1, Period1>, datetime::duration<Rep2, Period2> > | |
1584 | { | |
1585 | typedef datetime::duration<typename common_type<Rep1, Rep2>::type, | |
1586 | typename __ratio_gcd<Period1, Period2>::type> type; | |
1587 | }; | |
1588 | ||
1589 | namespace datetime { | |
1590 | ||
1591 | <font color="#c80000">// Duration ==</font> | |
1592 | ||
1593 | template <class LhsDuration, class RhsDuration> | |
1594 | struct __duration_eq | |
1595 | { | |
1596 | bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) | |
1597 | { | |
1598 | typedef typename common_type<LhsDuration, RhsDuration>::type CD; | |
1599 | return CD(lhs).count() == CD(rhs).count(); | |
1600 | } | |
1601 | }; | |
1602 | ||
1603 | template <class LhsDuration> | |
1604 | struct __duration_eq<LhsDuration, LhsDuration> | |
1605 | { | |
1606 | bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) | |
1607 | {return lhs.count() == rhs.count();} | |
1608 | }; | |
1609 | ||
1610 | template <class Rep1, class Period1, class Rep2, class Period2> | |
1611 | inline | |
1612 | bool | |
1613 | operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) | |
1614 | { | |
1615 | return __duration_eq<duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs); | |
1616 | } | |
1617 | ||
1618 | <font color="#c80000">// Duration !=</font> | |
1619 | ||
1620 | template <class Rep1, class Period1, class Rep2, class Period2> | |
1621 | inline | |
1622 | bool | |
1623 | operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) | |
1624 | { | |
1625 | return !(lhs == rhs); | |
1626 | } | |
1627 | ||
1628 | <font color="#c80000">// Duration <</font> | |
1629 | ||
1630 | template <class LhsDuration, class RhsDuration> | |
1631 | struct __duration_lt | |
1632 | { | |
1633 | bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) | |
1634 | { | |
1635 | typedef typename common_type<LhsDuration, RhsDuration>::type CD; | |
1636 | return CD(lhs).count() < CD(rhs).count(); | |
1637 | } | |
1638 | }; | |
1639 | ||
1640 | template <class LhsDuration> | |
1641 | struct __duration_lt<LhsDuration, LhsDuration> | |
1642 | { | |
1643 | bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) | |
1644 | {return lhs.count() < rhs.count();} | |
1645 | }; | |
1646 | ||
1647 | template <class Rep1, class Period1, class Rep2, class Period2> | |
1648 | inline | |
1649 | bool | |
1650 | operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) | |
1651 | { | |
1652 | return __duration_lt<duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs); | |
1653 | } | |
1654 | ||
1655 | <font color="#c80000">// Duration ></font> | |
1656 | ||
1657 | template <class Rep1, class Period1, class Rep2, class Period2> | |
1658 | inline | |
1659 | bool | |
1660 | operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) | |
1661 | { | |
1662 | return rhs < lhs; | |
1663 | } | |
1664 | ||
1665 | <font color="#c80000">// Duration <=</font> | |
1666 | ||
1667 | template <class Rep1, class Period1, class Rep2, class Period2> | |
1668 | inline | |
1669 | bool | |
1670 | operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) | |
1671 | { | |
1672 | return !(rhs < lhs); | |
1673 | } | |
1674 | ||
1675 | <font color="#c80000">// Duration >=</font> | |
1676 | ||
1677 | template <class Rep1, class Period1, class Rep2, class Period2> | |
1678 | inline | |
1679 | bool | |
1680 | operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) | |
1681 | { | |
1682 | return !(lhs < rhs); | |
1683 | } | |
1684 | ||
1685 | <font color="#c80000">// Duration +</font> | |
1686 | ||
1687 | template <class Rep1, class Period1, class Rep2, class Period2> | |
1688 | inline | |
1689 | typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type | |
1690 | operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) | |
1691 | { | |
1692 | typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type result = lhs; | |
1693 | result += rhs; | |
1694 | return result; | |
1695 | } | |
1696 | ||
1697 | <font color="#c80000">// Duration -</font> | |
1698 | ||
1699 | template <class Rep1, class Period1, class Rep2, class Period2> | |
1700 | inline | |
1701 | typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type | |
1702 | operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) | |
1703 | { | |
1704 | typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type result = lhs; | |
1705 | result -= rhs; | |
1706 | return result; | |
1707 | } | |
1708 | ||
1709 | <font color="#c80000">// Duration *</font> | |
1710 | ||
1711 | template <class Rep1, class Period, class Rep2> | |
1712 | inline | |
1713 | typename tmp::enable_if | |
1714 | < | |
1715 | tmp::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>::value && | |
1716 | tmp::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>::value, | |
1717 | duration<typename common_type<Rep1, Rep2>::type, Period> | |
1718 | >::type | |
1719 | operator*(const duration<Rep1, Period>& d, const Rep2& s) | |
1720 | { | |
1721 | typedef typename common_type<Rep1, Rep2>::type CR; | |
1722 | duration<CR, Period> r = d; | |
1723 | r *= static_cast<CR>(s); | |
1724 | return r; | |
1725 | } | |
1726 | ||
1727 | template <class Rep1, class Period, class Rep2> | |
1728 | inline | |
1729 | typename tmp::enable_if | |
1730 | < | |
1731 | tmp::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>::value && | |
1732 | tmp::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>::value, | |
1733 | duration<typename common_type<Rep1, Rep2>::type, Period> | |
1734 | >::type | |
1735 | operator*(const Rep1& s, const duration<Rep2, Period>& d) | |
1736 | { | |
1737 | return d * s; | |
1738 | } | |
1739 | ||
1740 | <font color="#c80000">// Duration /</font> | |
1741 | ||
1742 | template <class Duration, class Rep, bool = __is_duration<Rep>::value> | |
1743 | struct __duration_divide_result | |
1744 | { | |
1745 | }; | |
1746 | ||
1747 | template <class Duration, class Rep2, | |
1748 | bool = tmp::is_convertible<typename Duration::rep, | |
1749 | typename common_type<typename Duration::rep, Rep2>::type>::value && | |
1750 | tmp::is_convertible<Rep2, | |
1751 | typename common_type<typename Duration::rep, Rep2>::type>::value> | |
1752 | struct __duration_divide_imp | |
1753 | { | |
1754 | }; | |
1755 | ||
1756 | template <class Rep1, class Period, class Rep2> | |
1757 | struct __duration_divide_imp<duration<Rep1, Period>, Rep2, true> | |
1758 | { | |
1759 | typedef duration<typename common_type<Rep1, Rep2>::type, Period> type; | |
1760 | }; | |
1761 | ||
1762 | template <class Rep1, class Period, class Rep2> | |
1763 | struct __duration_divide_result<duration<Rep1, Period>, Rep2, false> | |
1764 | : __duration_divide_imp<duration<Rep1, Period>, Rep2> | |
1765 | { | |
1766 | }; | |
1767 | ||
1768 | template <class Rep1, class Period, class Rep2> | |
1769 | inline | |
1770 | typename __duration_divide_result<duration<Rep1, Period>, Rep2>::type | |
1771 | operator/(const duration<Rep1, Period>& d, const Rep2& s) | |
1772 | { | |
1773 | typedef typename common_type<Rep1, Rep2>::type CR; | |
1774 | duration<CR, Period> r = d; | |
1775 | r /= static_cast<CR>(s); | |
1776 | return r; | |
1777 | } | |
1778 | ||
1779 | template <class Rep1, class Period1, class Rep2, class Period2> | |
1780 | inline | |
1781 | typename common_type<Rep1, Rep2>::type | |
1782 | operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) | |
1783 | { | |
1784 | typedef typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type CD; | |
1785 | return CD(lhs).count() / CD(rhs).count(); | |
1786 | } | |
1787 | ||
1788 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
1789 | <font color="#c80000">///////////////////// time_point /////////////////////////</font> | |
1790 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
1791 | ||
1792 | template <class Clock, class Duration = typename Clock::duration> | |
1793 | class time_point | |
1794 | { | |
1795 | static char test1[__is_duration<Duration>::value]; | |
1796 | <font color="#c80000">// static_assert(__is_duration<Duration>::value,</font> | |
1797 | <font color="#c80000">// "Second template parameter of time_point must be a std::datetime::duration");</font> | |
1798 | public: | |
1799 | typedef Clock clock; | |
1800 | typedef Duration duration; | |
1801 | typedef typename duration::rep rep; | |
1802 | typedef typename duration::period period; | |
1803 | private: | |
1804 | duration d_; | |
1805 | ||
1806 | public: | |
1807 | time_point() : d_(duration::zero()) {} | |
1808 | explicit time_point(const duration& d) : d_(d) {} | |
1809 | ||
1810 | <font color="#c80000">// conversions</font> | |
1811 | template <class Duration2> | |
1812 | time_point(const time_point<clock, Duration2>& t, | |
1813 | typename tmp::enable_if | |
1814 | < | |
1815 | tmp::is_convertible<Duration2, duration>::value | |
1816 | >::type* = 0) | |
1817 | : d_(t.time_since_epoch()) {} | |
1818 | ||
1819 | <font color="#c80000">// observer</font> | |
1820 | ||
1821 | duration time_since_epoch() const {return d_;} | |
1822 | ||
1823 | <font color="#c80000">// arithmetic</font> | |
1824 | ||
1825 | time_point& operator+=(const duration& d) {d_ += d; return *this;} | |
1826 | time_point& operator-=(const duration& d) {d_ -= d; return *this;} | |
1827 | ||
1828 | <font color="#c80000">// special values</font> | |
1829 | ||
1830 | static time_point min() {return time_point(duration::min());} | |
1831 | static time_point max() {return time_point(duration::max());} | |
1832 | }; | |
1833 | ||
1834 | } <font color="#c80000">// datetime</font> | |
1835 | ||
1836 | template <class Clock, class Duration1, class Duration2> | |
1837 | struct common_type<datetime::time_point<Clock, Duration1>, datetime::time_point<Clock, Duration2> > | |
1838 | { | |
1839 | typedef datetime::time_point<Clock, typename common_type<Duration1, Duration2>::type> type; | |
1840 | }; | |
1841 | ||
1842 | namespace datetime { | |
1843 | ||
1844 | template <class ToDuration, class Clock, class Duration> | |
1845 | inline | |
1846 | time_point<Clock, ToDuration> | |
1847 | time_point_cast(const time_point<Clock, Duration>& t) | |
1848 | { | |
1849 | return time_point<Clock, ToDuration>(duration_cast<ToDuration>(t.time_since_epoch())); | |
1850 | } | |
1851 | ||
1852 | <font color="#c80000">// time_point ==</font> | |
1853 | ||
1854 | template <class Clock, class Duration1, class Duration2> | |
1855 | inline | |
1856 | bool | |
1857 | operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) | |
1858 | { | |
1859 | return lhs.time_since_epoch() == rhs.time_since_epoch(); | |
1860 | } | |
1861 | ||
1862 | <font color="#c80000">// time_point !=</font> | |
1863 | ||
1864 | template <class Clock, class Duration1, class Duration2> | |
1865 | inline | |
1866 | bool | |
1867 | operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) | |
1868 | { | |
1869 | return !(lhs == rhs); | |
1870 | } | |
1871 | ||
1872 | <font color="#c80000">// time_point <</font> | |
1873 | ||
1874 | template <class Clock, class Duration1, class Duration2> | |
1875 | inline | |
1876 | bool | |
1877 | operator<(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) | |
1878 | { | |
1879 | return lhs.time_since_epoch() < rhs.time_since_epoch(); | |
1880 | } | |
1881 | ||
1882 | <font color="#c80000">// time_point ></font> | |
1883 | ||
1884 | template <class Clock, class Duration1, class Duration2> | |
1885 | inline | |
1886 | bool | |
1887 | operator>(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) | |
1888 | { | |
1889 | return rhs < lhs; | |
1890 | } | |
1891 | ||
1892 | <font color="#c80000">// time_point <=</font> | |
1893 | ||
1894 | template <class Clock, class Duration1, class Duration2> | |
1895 | inline | |
1896 | bool | |
1897 | operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) | |
1898 | { | |
1899 | return !(rhs < lhs); | |
1900 | } | |
1901 | ||
1902 | <font color="#c80000">// time_point >=</font> | |
1903 | ||
1904 | template <class Clock, class Duration1, class Duration2> | |
1905 | inline | |
1906 | bool | |
1907 | operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) | |
1908 | { | |
1909 | return !(lhs < rhs); | |
1910 | } | |
1911 | ||
1912 | <font color="#c80000">// time_point operator+(time_point x, duration y);</font> | |
1913 | ||
1914 | template <class Clock, class Duration1, class Rep2, class Period2> | |
1915 | inline | |
1916 | time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> | |
1917 | operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs) | |
1918 | { | |
1919 | typedef time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> TimeResult; | |
1920 | TimeResult r(lhs); | |
1921 | r += rhs; | |
1922 | return r; | |
1923 | } | |
1924 | ||
1925 | <font color="#c80000">// time_point operator+(duration x, time_point y);</font> | |
1926 | ||
1927 | template <class Rep1, class Period1, class Clock, class Duration2> | |
1928 | inline | |
1929 | time_point<Clock, typename common_type<duration<Rep1, Period1>, Duration2>::type> | |
1930 | operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs) | |
1931 | { | |
1932 | return rhs + lhs; | |
1933 | } | |
1934 | ||
1935 | <font color="#c80000">// time_point operator-(time_point x, duration y);</font> | |
1936 | ||
1937 | template <class Clock, class Duration1, class Rep2, class Period2> | |
1938 | inline | |
1939 | time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> | |
1940 | operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs) | |
1941 | { | |
1942 | return lhs + (-rhs); | |
1943 | } | |
1944 | ||
1945 | <font color="#c80000">// duration operator-(time_point x, time_point y);</font> | |
1946 | ||
1947 | template <class Clock, class Duration1, class Duration2> | |
1948 | inline | |
1949 | typename common_type<Duration1, Duration2>::type | |
1950 | operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs) | |
1951 | { | |
1952 | return lhs.time_since_epoch() - rhs.time_since_epoch(); | |
1953 | } | |
1954 | ||
1955 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
1956 | <font color="#c80000">/////////////////////// clocks ///////////////////////////</font> | |
1957 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
1958 | ||
1959 | <font color="#c80000">// If you're porting, clocks are the system-specific (non-portable) part.</font> | |
1960 | <font color="#c80000">// You'll need to know how to get the current time and implement that under now().</font> | |
1961 | <font color="#c80000">// You'll need to know what units (tick period) and representation makes the most</font> | |
1962 | <font color="#c80000">// sense for your clock and set those accordingly.</font> | |
1963 | <font color="#c80000">// If you know how to map this clock to time_t (perhaps your clock is std::time, which</font> | |
1964 | <font color="#c80000">// makes that trivial), then you can fill out system_clock's to_time_t() and from_time_t().</font> | |
1965 | ||
1966 | class system_clock | |
1967 | { | |
1968 | public: | |
1969 | typedef microseconds duration; | |
1970 | typedef duration::rep rep; | |
1971 | typedef duration::period period; | |
1972 | typedef datetime::time_point<system_clock> time_point; | |
1973 | static const bool is_monotonic = false; | |
1974 | ||
1975 | static time_point now(); | |
1976 | static time_t to_time_t (const time_point& t); | |
1977 | static time_point from_time_t(time_t t); | |
1978 | }; | |
1979 | ||
1980 | class monotonic_clock | |
1981 | { | |
1982 | public: | |
1983 | typedef nanoseconds duration; | |
1984 | typedef duration::rep rep; | |
1985 | typedef duration::period period; | |
1986 | typedef datetime::time_point<monotonic_clock> time_point; | |
1987 | static const bool is_monotonic = true; | |
1988 | ||
1989 | static time_point now(); | |
1990 | }; | |
1991 | ||
1992 | typedef monotonic_clock high_resolution_clock; | |
1993 | ||
1994 | } <font color="#c80000">// datetime</font> | |
1995 | } <font color="#c80000">// std</font> | |
1996 | ||
1997 | <font color="#c80000">// clocks.cpp</font> | |
1998 | ||
1999 | #include <sys/time.h> <font color="#c80000">//for gettimeofday and timeval</font> | |
2000 | #include <mach/mach_time.h> <font color="#c80000">// mach_absolute_time, mach_timebase_info_data_t</font> | |
2001 | ||
2002 | namespace std { | |
2003 | namespace datetime { | |
2004 | ||
2005 | <font color="#c80000">// system_clock</font> | |
2006 | ||
2007 | <font color="#c80000">// gettimeofday is the most precise "system time" available on this platform.</font> | |
2008 | <font color="#c80000">// It returns the number of microseconds since New Years 1970 in a struct called timeval</font> | |
2009 | <font color="#c80000">// which has a field for seconds and a field for microseconds.</font> | |
2010 | <font color="#c80000">// Fill in the timeval and then convert that to the time_point</font> | |
2011 | system_clock::time_point | |
2012 | system_clock::now() | |
2013 | { | |
2014 | timeval tv; | |
2015 | gettimeofday(&tv, 0); | |
2016 | return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); | |
2017 | } | |
2018 | ||
2019 | <font color="#c80000">// Take advantage of the fact that on this platform time_t is nothing but</font> | |
2020 | <font color="#c80000">// an integral count of seconds since New Years 1970 (same epoch as timeval).</font> | |
2021 | <font color="#c80000">// Just get the duration out of the time_point and truncate it to seconds.</font> | |
2022 | time_t | |
2023 | system_clock::to_time_t(const time_point& t) | |
2024 | { | |
2025 | return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); | |
2026 | } | |
2027 | ||
2028 | <font color="#c80000">// Just turn the time_t into a count of seconds and construct a time_point with it.</font> | |
2029 | system_clock::time_point | |
2030 | system_clock::from_time_t(time_t t) | |
2031 | { | |
2032 | return system_clock::time_point(seconds(t)); | |
2033 | } | |
2034 | ||
2035 | <font color="#c80000">// monotonic_clock</font> | |
2036 | ||
2037 | <font color="#c80000">// Note, in this implementation monotonic_clock and high_resolution_clock</font> | |
2038 | <font color="#c80000">// are the same clock. They are both based on mach_absolute_time().</font> | |
2039 | <font color="#c80000">// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of</font> | |
2040 | <font color="#c80000">// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom</font> | |
2041 | <font color="#c80000">// are run time constants supplied by the OS. This clock has no relationship</font> | |
2042 | <font color="#c80000">// to the Gregorian calendar. It's main use is as a high resolution timer.</font> | |
2043 | ||
2044 | <font color="#c80000">// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize</font> | |
2045 | <font color="#c80000">// for that case as an optimization.</font> | |
2046 | static | |
2047 | monotonic_clock::rep | |
2048 | monotonic_simplified() | |
2049 | { | |
2050 | return mach_absolute_time(); | |
2051 | } | |
2052 | ||
2053 | static | |
2054 | double | |
2055 | compute_monotonic_factor() | |
2056 | { | |
2057 | mach_timebase_info_data_t MachInfo; | |
2058 | mach_timebase_info(&MachInfo); | |
2059 | return static_cast<double>(MachInfo.numer) / MachInfo.denom; | |
2060 | } | |
2061 | ||
2062 | static | |
2063 | monotonic_clock::rep | |
2064 | monotonic_full() | |
2065 | { | |
2066 | static const double factor = compute_monotonic_factor(); | |
2067 | return static_cast<monotonic_clock::rep>(mach_absolute_time() * factor); | |
2068 | } | |
2069 | ||
2070 | typedef monotonic_clock::rep (*FP)(); | |
2071 | ||
2072 | static | |
2073 | FP | |
2074 | init_monotonic_clock() | |
2075 | { | |
2076 | mach_timebase_info_data_t MachInfo; | |
2077 | mach_timebase_info(&MachInfo); | |
2078 | if (MachInfo.numer == MachInfo.denom) | |
2079 | return &monotonic_simplified; | |
2080 | return &monotonic_full; | |
2081 | } | |
2082 | ||
2083 | monotonic_clock::time_point | |
2084 | monotonic_clock::now() | |
2085 | { | |
2086 | static FP fp = init_monotonic_clock(); | |
2087 | return time_point(duration(fp())); | |
2088 | } | |
2089 | ||
2090 | <font color="#c80000">// clocks.cpp end</font> | |
2091 | ||
2092 | } } <font color="#c80000">// std::datetime</font> | |
2093 | ||
2094 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
2095 | <font color="#c80000">///////////// simulated thread interface /////////////////</font> | |
2096 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
2097 | ||
2098 | #include <iostream> | |
2099 | ||
2100 | namespace std { | |
2101 | ||
2102 | void __print_time(datetime::system_clock::time_point t) | |
2103 | { | |
2104 | using namespace datetime; | |
2105 | time_t c_time = system_clock::to_time_t(t); | |
2106 | std::tm* tmptr = std::localtime(&c_time); | |
2107 | system_clock::duration d = t.time_since_epoch(); | |
2108 | std::cout << tmptr->tm_hour << ':' << tmptr->tm_min << ':' << tmptr->tm_sec | |
2109 | << '.' << (d - duration_cast<seconds>(d)).count(); | |
2110 | } | |
2111 | ||
2112 | namespace this_thread { | |
2113 | ||
2114 | template <class Rep, class Period> | |
2115 | void sleep_for(const datetime::duration<Rep, Period>& d) | |
2116 | { | |
2117 | datetime::microseconds t = datetime::duration_cast<datetime::microseconds>(d); | |
2118 | if (t < d) | |
2119 | ++t; | |
2120 | if (t > datetime::microseconds(0)) | |
2121 | std::cout << "sleep_for " << t.count() << " microseconds\n"; | |
2122 | } | |
2123 | ||
2124 | template <class Clock, class Duration> | |
2125 | void sleep_until(const datetime::time_point<Clock, Duration>& t) | |
2126 | { | |
2127 | using namespace datetime; | |
2128 | typedef time_point<Clock, Duration> Time; | |
2129 | typedef system_clock::time_point SysTime; | |
2130 | if (t > Clock::now()) | |
2131 | { | |
2132 | typedef typename common_type<typename Time::duration, typename SysTime::duration>::type D; | |
2133 | <font color="#c80000">/* auto */</font> D d = t - Clock::now(); | |
2134 | microseconds us = duration_cast<microseconds>(d); | |
2135 | if (us < d) | |
2136 | ++us; | |
2137 | SysTime st = system_clock::now() + us; | |
2138 | std::cout << "sleep_until "; | |
2139 | __print_time(st); | |
2140 | std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n"; | |
2141 | } | |
2142 | } | |
2143 | ||
2144 | } <font color="#c80000">// this_thread</font> | |
2145 | ||
2146 | struct mutex {}; | |
2147 | ||
2148 | struct timed_mutex | |
2149 | { | |
2150 | bool try_lock() {std::cout << "timed_mutex::try_lock()\n";} | |
2151 | ||
2152 | template <class Rep, class Period> | |
2153 | bool try_lock_for(const datetime::duration<Rep, Period>& d) | |
2154 | { | |
2155 | datetime::microseconds t = datetime::duration_cast<datetime::microseconds>(d); | |
2156 | if (t <= datetime::microseconds(0)) | |
2157 | return try_lock(); | |
2158 | std::cout << "try_lock_for " << t.count() << " microseconds\n"; | |
2159 | return true; | |
2160 | } | |
2161 | ||
2162 | template <class Clock, class Duration> | |
2163 | bool try_lock_until(const datetime::time_point<Clock, Duration>& t) | |
2164 | { | |
2165 | using namespace datetime; | |
2166 | typedef time_point<Clock, Duration> Time; | |
2167 | typedef system_clock::time_point SysTime; | |
2168 | if (t <= Clock::now()) | |
2169 | return try_lock(); | |
2170 | typedef typename common_type<typename Time::duration, typename Clock::duration>::type D; | |
2171 | <font color="#c80000">/* auto */</font> D d = t - Clock::now(); | |
2172 | microseconds us = duration_cast<microseconds>(d); | |
2173 | SysTime st = system_clock::now() + us; | |
2174 | std::cout << "try_lock_until "; | |
2175 | __print_time(st); | |
2176 | std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n"; | |
2177 | } | |
2178 | }; | |
2179 | ||
2180 | struct condition_variable | |
2181 | { | |
2182 | template <class Rep, class Period> | |
2183 | bool wait_for(mutex&, const datetime::duration<Rep, Period>& d) | |
2184 | { | |
2185 | datetime::microseconds t = datetime::duration_cast<datetime::microseconds>(d); | |
2186 | std::cout << "wait_for " << t.count() << " microseconds\n"; | |
2187 | return true; | |
2188 | } | |
2189 | ||
2190 | template <class Clock, class Duration> | |
2191 | bool wait_until(mutex&, const datetime::time_point<Clock, Duration>& t) | |
2192 | { | |
2193 | using namespace datetime; | |
2194 | typedef time_point<Clock, Duration> Time; | |
2195 | typedef system_clock::time_point SysTime; | |
2196 | if (t <= Clock::now()) | |
2197 | return false; | |
2198 | typedef typename common_type<typename Time::duration, typename Clock::duration>::type D; | |
2199 | <font color="#c80000">/* auto */</font> D d = t - Clock::now(); | |
2200 | microseconds us = duration_cast<microseconds>(d); | |
2201 | SysTime st = system_clock::now() + us; | |
2202 | std::cout << "wait_until "; | |
2203 | __print_time(st); | |
2204 | std::cout << " which is " << (st - system_clock::now()).count() << " microseconds away\n"; | |
2205 | } | |
2206 | }; | |
2207 | ||
2208 | } <font color="#c80000">// std</font> | |
2209 | ||
2210 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
2211 | <font color="#c80000">/////////////////// End of implemetation ////////////////</font> | |
2212 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
2213 | ||
2214 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
2215 | <font color="#c80000">//////////// Simple sleep and wait examples //////////////</font> | |
2216 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
2217 | ||
2218 | std::mutex m; | |
2219 | std::timed_mutex mut; | |
2220 | std::condition_variable cv; | |
2221 | ||
2222 | void basic_examples() | |
2223 | { | |
2224 | std::cout << "Running basic examples\n"; | |
2225 | using namespace std; | |
2226 | using namespace std::datetime; | |
2227 | system_clock::time_point time_limit = system_clock::now() + seconds(4) + milliseconds(500); | |
2228 | this_thread::sleep_for(seconds(3)); | |
2229 | this_thread::sleep_for(nanoseconds(300)); | |
2230 | this_thread::sleep_until(time_limit); | |
2231 | <font color="#c80000">// this_thread::sleep_for(time_limit); // desired compile-time error</font> | |
2232 | <font color="#c80000">// this_thread::sleep_until(seconds(3)); // desired compile-time error</font> | |
2233 | mut.try_lock_for(milliseconds(30)); | |
2234 | mut.try_lock_until(time_limit); | |
2235 | <font color="#c80000">// mut.try_lock_for(time_limit); // desired compile-time error</font> | |
2236 | <font color="#c80000">// mut.try_lock_until(milliseconds(30)); // desired compile-time error</font> | |
2237 | cv.wait_for(m, minutes(1)); <font color="#c80000">// real code would put this in a loop</font> | |
2238 | cv.wait_until(m, time_limit); <font color="#c80000">// real code would put this in a loop</font> | |
2239 | <font color="#c80000">// For those who prefer floating point</font> | |
2240 | this_thread::sleep_for(duration<double>(0.25)); | |
2241 | this_thread::sleep_until(system_clock::now() + duration<double>(1.5)); | |
2242 | } | |
2243 | ||
2244 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
2245 | <font color="#c80000">//////////////////// User1 Example ///////////////////////</font> | |
2246 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
2247 | ||
2248 | namespace User1 | |
2249 | { | |
2250 | <font color="#c80000">// Example type-safe "physics" code interoperating with std::datetime::duration types</font> | |
2251 | <font color="#c80000">// and taking advantage of the std::ratio infrastructure and design philosophy.</font> | |
2252 | ||
2253 | <font color="#c80000">// length - mimics std::datetime::duration except restricts representation to double.</font> | |
2254 | <font color="#c80000">// Uses std::ratio facilities for length units conversions.</font> | |
2255 | ||
2256 | template <class Ratio> | |
2257 | class length | |
2258 | { | |
2259 | public: | |
2260 | typedef Ratio ratio; | |
2261 | private: | |
2262 | double len_; | |
2263 | public: | |
2264 | ||
2265 | length() : len_(1) {} | |
2266 | length(const double& len) : len_(len) {} | |
2267 | ||
2268 | <font color="#c80000">// conversions</font> | |
2269 | template <class R> | |
2270 | length(const length<R>& d) | |
2271 | : len_(d.count() * std::ratio_divide<Ratio, R>::type::den / | |
2272 | std::ratio_divide<Ratio, R>::type::num) {} | |
2273 | ||
2274 | <font color="#c80000">// observer</font> | |
2275 | ||
2276 | double count() const {return len_;} | |
2277 | ||
2278 | <font color="#c80000">// arithmetic</font> | |
2279 | ||
2280 | length& operator+=(const length& d) {len_ += d.count(); return *this;} | |
2281 | length& operator-=(const length& d) {len_ -= d.count(); return *this;} | |
2282 | ||
2283 | length operator+() const {return *this;} | |
2284 | length operator-() const {return length(-len_);} | |
2285 | ||
2286 | length& operator*=(double rhs) {len_ *= rhs; return *this;} | |
2287 | length& operator/=(double rhs) {len_ /= rhs; return *this;} | |
2288 | }; | |
2289 | ||
2290 | <font color="#c80000">// Sparse sampling of length units</font> | |
2291 | typedef length<std::ratio<1> > meter; <font color="#c80000">// set meter as "unity"</font> | |
2292 | typedef length<std::centi> centimeter; <font color="#c80000">// 1/100 meter</font> | |
2293 | typedef length<std::kilo> kilometer; <font color="#c80000">// 1000 meters</font> | |
2294 | typedef length<std::ratio<254, 10000> > inch; <font color="#c80000">// 254/10000 meters</font> | |
2295 | <font color="#c80000">// length takes ratio instead of two integral types so that definitions can be made like so:</font> | |
2296 | typedef length<std::ratio_multiply<std::ratio<12>, inch::ratio>::type> foot; <font color="#c80000">// 12 inchs</font> | |
2297 | typedef length<std::ratio_multiply<std::ratio<5280>, foot::ratio>::type> mile; <font color="#c80000">// 5280 feet</font> | |
2298 | ||
2299 | <font color="#c80000">// Need a floating point definition of seconds</font> | |
2300 | typedef std::datetime::duration<double> seconds; <font color="#c80000">// unity</font> | |
2301 | <font color="#c80000">// Demo of (scientific) support for sub-nanosecond resolutions</font> | |
2302 | typedef std::datetime::duration<double, std::pico> picosecond; <font color="#c80000">// 10^-12 seconds</font> | |
2303 | typedef std::datetime::duration<double, std::femto> femtosecond; <font color="#c80000">// 10^-15 seconds</font> | |
2304 | typedef std::datetime::duration<double, std::atto> attosecond; <font color="#c80000">// 10^-18 seconds</font> | |
2305 | ||
2306 | <font color="#c80000">// A very brief proof-of-concept for SIUnits-like library</font> | |
2307 | <font color="#c80000">// Hard-wired to floating point seconds and meters, but accepts other units (shown in testUser1())</font> | |
2308 | template <class R1, class R2> | |
2309 | class quantity | |
2310 | { | |
2311 | double q_; | |
2312 | public: | |
2313 | quantity() : q_(1) {} | |
2314 | ||
2315 | double get() const {return q_;} | |
2316 | void set(double q) {q_ = q;} | |
2317 | }; | |
2318 | ||
2319 | template <> | |
2320 | class quantity<std::ratio<1>, std::ratio<0> > | |
2321 | { | |
2322 | double q_; | |
2323 | public: | |
2324 | quantity() : q_(1) {} | |
2325 | quantity(seconds d) : q_(d.count()) {} <font color="#c80000">// note: only User1::seconds needed here</font> | |
2326 | ||
2327 | double get() const {return q_;} | |
2328 | void set(double q) {q_ = q;} | |
2329 | }; | |
2330 | ||
2331 | template <> | |
2332 | class quantity<std::ratio<0>, std::ratio<1> > | |
2333 | { | |
2334 | double q_; | |
2335 | public: | |
2336 | quantity() : q_(1) {} | |
2337 | quantity(meter d) : q_(d.count()) {} <font color="#c80000">// note: only User1::meter needed here</font> | |
2338 | ||
2339 | double get() const {return q_;} | |
2340 | void set(double q) {q_ = q;} | |
2341 | }; | |
2342 | ||
2343 | template <> | |
2344 | class quantity<std::ratio<0>, std::ratio<0> > | |
2345 | { | |
2346 | double q_; | |
2347 | public: | |
2348 | quantity() : q_(1) {} | |
2349 | quantity(double d) : q_(d) {} | |
2350 | ||
2351 | double get() const {return q_;} | |
2352 | void set(double q) {q_ = q;} | |
2353 | }; | |
2354 | ||
2355 | <font color="#c80000">// Example SI-Units</font> | |
2356 | typedef quantity<std::ratio<0>, std::ratio<0> > Scalar; | |
2357 | typedef quantity<std::ratio<1>, std::ratio<0> > Time; <font color="#c80000">// second</font> | |
2358 | typedef quantity<std::ratio<0>, std::ratio<1> > Distance; <font color="#c80000">// meter</font> | |
2359 | typedef quantity<std::ratio<-1>, std::ratio<1> > Speed; <font color="#c80000">// meter/second</font> | |
2360 | typedef quantity<std::ratio<-2>, std::ratio<1> > Acceleration; <font color="#c80000">// meter/second^2</font> | |
2361 | ||
2362 | template <class R1, class R2, class R3, class R4> | |
2363 | quantity<typename std::ratio_subtract<R1, R3>::type, typename std::ratio_subtract<R2, R4>::type> | |
2364 | operator/(const quantity<R1, R2>& x, const quantity<R3, R4>& y) | |
2365 | { | |
2366 | typedef quantity<typename std::ratio_subtract<R1, R3>::type, typename std::ratio_subtract<R2, R4>::type> R; | |
2367 | R r; | |
2368 | r.set(x.get() / y.get()); | |
2369 | return r; | |
2370 | } | |
2371 | ||
2372 | template <class R1, class R2, class R3, class R4> | |
2373 | quantity<typename std::ratio_add<R1, R3>::type, typename std::ratio_add<R2, R4>::type> | |
2374 | operator*(const quantity<R1, R2>& x, const quantity<R3, R4>& y) | |
2375 | { | |
2376 | typedef quantity<typename std::ratio_add<R1, R3>::type, typename std::ratio_add<R2, R4>::type> R; | |
2377 | R r; | |
2378 | r.set(x.get() * y.get()); | |
2379 | return r; | |
2380 | } | |
2381 | ||
2382 | template <class R1, class R2> | |
2383 | quantity<R1, R2> | |
2384 | operator+(const quantity<R1, R2>& x, const quantity<R1, R2>& y) | |
2385 | { | |
2386 | typedef quantity<R1, R2> R; | |
2387 | R r; | |
2388 | r.set(x.get() + y.get()); | |
2389 | return r; | |
2390 | } | |
2391 | ||
2392 | template <class R1, class R2> | |
2393 | quantity<R1, R2> | |
2394 | operator-(const quantity<R1, R2>& x, const quantity<R1, R2>& y) | |
2395 | { | |
2396 | typedef quantity<R1, R2> R; | |
2397 | R r; | |
2398 | r.set(x.get() - y.get()); | |
2399 | return r; | |
2400 | } | |
2401 | ||
2402 | <font color="#c80000">// Example type-safe physics function</font> | |
2403 | Distance | |
2404 | compute_distance(Speed v0, Time t, Acceleration a) | |
2405 | { | |
2406 | return v0 * t + Scalar(.5) * a * t * t; <font color="#c80000">// if a units mistake is made here it won't compile</font> | |
2407 | } | |
2408 | ||
2409 | } <font color="#c80000">// User1</font> | |
2410 | ||
2411 | #include <iostream> | |
2412 | ||
2413 | <font color="#c80000">// Exercise example type-safe physics function and show interoperation</font> | |
2414 | <font color="#c80000">// of custom time durations (User1::seconds) and standard time durations (std::hours).</font> | |
2415 | <font color="#c80000">// Though input can be arbitrary (but type-safe) units, output is always in SI-units</font> | |
2416 | <font color="#c80000">// (a limitation of the simplified Units lib demoed here).</font> | |
2417 | void testUser1() | |
2418 | { | |
2419 | std::cout << "*************\n"; | |
2420 | std::cout << "* testUser1 *\n"; | |
2421 | std::cout << "*************\n"; | |
2422 | User1::Distance d( User1::mile(110) ); | |
2423 | User1::Time t( std::datetime::hours(2) ); | |
2424 | User1::Speed s = d / t; | |
2425 | std::cout << "Speed = " << s.get() << " meters/sec\n"; | |
2426 | User1::Acceleration a = User1::Distance( User1::foot(32.2) ) / User1::Time() / User1::Time(); | |
2427 | std::cout << "Acceleration = " << a.get() << " meters/sec^2\n"; | |
2428 | User1::Distance df = compute_distance(s, User1::Time( User1::seconds(0.5) ), a); | |
2429 | std::cout << "Distance = " << df.get() << " meters\n"; | |
2430 | std::cout << "There are " << User1::mile::ratio::den << '/' << User1::mile::ratio::num << " miles/meter"; | |
2431 | User1::meter mt = 1; | |
2432 | User1::mile mi = mt; | |
2433 | std::cout << " which is approximately " << mi.count() << '\n'; | |
2434 | std::cout << "There are " << User1::mile::ratio::num << '/' << User1::mile::ratio::den << " meters/mile"; | |
2435 | mi = 1; | |
2436 | mt = mi; | |
2437 | std::cout << " which is approximately " << mt.count() << '\n'; | |
2438 | User1::attosecond as(1); | |
2439 | User1::seconds sec = as; | |
2440 | std::cout << "1 attosecond is " << sec.count() << " seconds\n"; | |
2441 | std::cout << "sec = as; <font color="#c80000">// compiles\n";</font> | |
2442 | sec = User1::seconds(1); | |
2443 | as = sec; | |
2444 | std::cout << "1 second is " << as.count() << " attoseconds\n"; | |
2445 | std::cout << "as = sec; <font color="#c80000">// compiles\n";</font> | |
2446 | std::cout << "\n"; | |
2447 | } | |
2448 | ||
2449 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
2450 | <font color="#c80000">//////////////////// User2 Example ///////////////////////</font> | |
2451 | <font color="#c80000">//////////////////////////////////////////////////////////</font> | |
2452 | ||
2453 | <font color="#c80000">// Demonstrate User2:</font> | |
2454 | <font color="#c80000">// A "saturating" signed integral type is developed. This type has +/- infinity and a nan</font> | |
2455 | <font color="#c80000">// (like IEEE floating point) but otherwise obeys signed integral arithmetic.</font> | |
2456 | <font color="#c80000">// This class is subsequently used as the rep in std::datetime::duration to demonstrate a</font> | |
2457 | <font color="#c80000">// duration class that does not silently ignore overflow.</font> | |
2458 | #include <ostream> | |
2459 | #include <stdexcept> | |
2460 | #include <climits> | |
2461 | ||
2462 | namespace User2 | |
2463 | { | |
2464 | ||
2465 | template <class I> | |
2466 | class saturate | |
2467 | { | |
2468 | public: | |
2469 | typedef I int_type; | |
2470 | ||
2471 | static const int_type nan = int_type(int_type(1) << (sizeof(int_type) * CHAR_BIT - 1)); | |
2472 | static const int_type neg_inf = nan + 1; | |
2473 | static const int_type pos_inf = -neg_inf; | |
2474 | private: | |
2475 | int_type i_; | |
2476 | ||
2477 | <font color="#c80000">// static_assert(std::is_integral<int_type>::value && std::is_signed<int_type>::value,</font> | |
2478 | <font color="#c80000">// "saturate only accepts signed integral types");</font> | |
2479 | <font color="#c80000">// static_assert(nan == -nan && neg_inf < pos_inf,</font> | |
2480 | <font color="#c80000">// "saturate assumes two's complement hardware for signed integrals");</font> | |
2481 | ||
2482 | public: | |
2483 | saturate() : i_(nan) {} | |
2484 | explicit saturate(int_type i) : i_(i) {} | |
2485 | <font color="#c80000">// explicit</font> | |
2486 | operator int_type() const; | |
2487 | ||
2488 | saturate& operator+=(saturate x); | |
2489 | saturate& operator-=(saturate x) {return *this += -x;} | |
2490 | saturate& operator*=(saturate x); | |
2491 | saturate& operator/=(saturate x); | |
2492 | saturate& operator%=(saturate x); | |
2493 | ||
2494 | saturate operator- () const {return saturate(-i_);} | |
2495 | saturate& operator++() {*this += saturate(int_type(1)); return *this;} | |
2496 | saturate operator++(int) {saturate tmp(*this); ++(*this); return tmp;} | |
2497 | saturate& operator--() {*this -= saturate(int_type(1)); return *this;} | |
2498 | saturate operator--(int) {saturate tmp(*this); --(*this); return tmp;} | |
2499 | ||
2500 | friend saturate operator+(saturate x, saturate y) {return x += y;} | |
2501 | friend saturate operator-(saturate x, saturate y) {return x -= y;} | |
2502 | friend saturate operator*(saturate x, saturate y) {return x *= y;} | |
2503 | friend saturate operator/(saturate x, saturate y) {return x /= y;} | |
2504 | friend saturate operator%(saturate x, saturate y) {return x %= y;} | |
2505 | ||
2506 | friend bool operator==(saturate x, saturate y) | |
2507 | { | |
2508 | if (x.i_ == nan || y.i_ == nan) | |
2509 | return false; | |
2510 | return x.i_ == y.i_; | |
2511 | } | |
2512 | ||
2513 | friend bool operator!=(saturate x, saturate y) {return !(x == y);} | |
2514 | ||
2515 | friend bool operator<(saturate x, saturate y) | |
2516 | { | |
2517 | if (x.i_ == nan || y.i_ == nan) | |
2518 | return false; | |
2519 | return x.i_ < y.i_; | |
2520 | } | |
2521 | ||
2522 | friend bool operator<=(saturate x, saturate y) | |
2523 | { | |
2524 | if (x.i_ == nan || y.i_ == nan) | |
2525 | return false; | |
2526 | return x.i_ <= y.i_; | |
2527 | } | |
2528 | ||
2529 | friend bool operator>(saturate x, saturate y) | |
2530 | { | |
2531 | if (x.i_ == nan || y.i_ == nan) | |
2532 | return false; | |
2533 | return x.i_ > y.i_; | |
2534 | } | |
2535 | ||
2536 | friend bool operator>=(saturate x, saturate y) | |
2537 | { | |
2538 | if (x.i_ == nan || y.i_ == nan) | |
2539 | return false; | |
2540 | return x.i_ >= y.i_; | |
2541 | } | |
2542 | ||
2543 | friend std::ostream& operator<<(std::ostream& os, saturate s) | |
2544 | { | |
2545 | switch (s.i_) | |
2546 | { | |
2547 | case pos_inf: | |
2548 | return os << "inf"; | |
2549 | case nan: | |
2550 | return os << "nan"; | |
2551 | case neg_inf: | |
2552 | return os << "-inf"; | |
2553 | }; | |
2554 | return os << s.i_; | |
2555 | } | |
2556 | }; | |
2557 | ||
2558 | template <class I> | |
2559 | saturate<I>::operator int_type() const | |
2560 | { | |
2561 | switch (i_) | |
2562 | { | |
2563 | case nan: | |
2564 | case neg_inf: | |
2565 | case pos_inf: | |
2566 | throw std::out_of_range("saturate special value can not convert to int_type"); | |
2567 | } | |
2568 | return i_; | |
2569 | } | |
2570 | ||
2571 | template <class I> | |
2572 | saturate<I>& | |
2573 | saturate<I>::operator+=(saturate x) | |
2574 | { | |
2575 | switch (i_) | |
2576 | { | |
2577 | case pos_inf: | |
2578 | switch (x.i_) | |
2579 | { | |
2580 | case neg_inf: | |
2581 | case nan: | |
2582 | i_ = nan; | |
2583 | } | |
2584 | return *this; | |
2585 | case nan: | |
2586 | return *this; | |
2587 | case neg_inf: | |
2588 | switch (x.i_) | |
2589 | { | |
2590 | case pos_inf: | |
2591 | case nan: | |
2592 | i_ = nan; | |
2593 | } | |
2594 | return *this; | |
2595 | } | |
2596 | switch (x.i_) | |
2597 | { | |
2598 | case pos_inf: | |
2599 | case neg_inf: | |
2600 | case nan: | |
2601 | i_ = x.i_; | |
2602 | return *this; | |
2603 | } | |
2604 | if (x.i_ >= 0) | |
2605 | { | |
2606 | if (i_ < pos_inf - x.i_) | |
2607 | i_ += x.i_; | |
2608 | else | |
2609 | i_ = pos_inf; | |
2610 | return *this; | |
2611 | } | |
2612 | if (i_ > neg_inf - x.i_) | |
2613 | i_ += x.i_; | |
2614 | else | |
2615 | i_ = neg_inf; | |
2616 | return *this; | |
2617 | } | |
2618 | ||
2619 | template <class I> | |
2620 | saturate<I>& | |
2621 | saturate<I>::operator*=(saturate x) | |
2622 | { | |
2623 | switch (i_) | |
2624 | { | |
2625 | case 0: | |
2626 | switch (x.i_) | |
2627 | { | |
2628 | case pos_inf: | |
2629 | case neg_inf: | |
2630 | case nan: | |
2631 | i_ = nan; | |
2632 | } | |
2633 | return *this; | |
2634 | case pos_inf: | |
2635 | switch (x.i_) | |
2636 | { | |
2637 | case nan: | |
2638 | case 0: | |
2639 | i_ = nan; | |
2640 | return *this; | |
2641 | } | |
2642 | if (x.i_ < 0) | |
2643 | i_ = neg_inf; | |
2644 | return *this; | |
2645 | case nan: | |
2646 | return *this; | |
2647 | case neg_inf: | |
2648 | switch (x.i_) | |
2649 | { | |
2650 | case nan: | |
2651 | case 0: | |
2652 | i_ = nan; | |
2653 | return *this; | |
2654 | } | |
2655 | if (x.i_ < 0) | |
2656 | i_ = pos_inf; | |
2657 | return *this; | |
2658 | } | |
2659 | switch (x.i_) | |
2660 | { | |
2661 | case 0: | |
2662 | i_ = 0; | |
2663 | return *this; | |
2664 | case nan: | |
2665 | i_ = nan; | |
2666 | return *this; | |
2667 | case pos_inf: | |
2668 | if (i_ < 0) | |
2669 | i_ = neg_inf; | |
2670 | else | |
2671 | i_ = pos_inf; | |
2672 | return *this; | |
2673 | case neg_inf: | |
2674 | if (i_ < 0) | |
2675 | i_ = pos_inf; | |
2676 | else | |
2677 | i_ = neg_inf; | |
2678 | return *this; | |
2679 | } | |
2680 | int s = (i_ < 0 ? -1 : 1) * (x.i_ < 0 ? -1 : 1); | |
2681 | i_ = i_ < 0 ? -i_ : i_; | |
2682 | int_type x_i_ = x.i_ < 0 ? -x.i_ : x.i_; | |
2683 | if (i_ <= pos_inf / x_i_) | |
2684 | i_ *= x_i_; | |
2685 | else | |
2686 | i_ = pos_inf; | |
2687 | i_ *= s; | |
2688 | return *this; | |
2689 | } | |
2690 | ||
2691 | template <class I> | |
2692 | saturate<I>& | |
2693 | saturate<I>::operator/=(saturate x) | |
2694 | { | |
2695 | switch (x.i_) | |
2696 | { | |
2697 | case pos_inf: | |
2698 | case neg_inf: | |
2699 | switch (i_) | |
2700 | { | |
2701 | case pos_inf: | |
2702 | case neg_inf: | |
2703 | case nan: | |
2704 | i_ = nan; | |
2705 | break; | |
2706 | default: | |
2707 | i_ = 0; | |
2708 | break; | |
2709 | } | |
2710 | return *this; | |
2711 | case nan: | |
2712 | i_ = nan; | |
2713 | return *this; | |
2714 | case 0: | |
2715 | switch (i_) | |
2716 | { | |
2717 | case pos_inf: | |
2718 | case neg_inf: | |
2719 | case nan: | |
2720 | return *this; | |
2721 | case 0: | |
2722 | i_ = nan; | |
2723 | return *this; | |
2724 | } | |
2725 | if (i_ > 0) | |
2726 | i_ = pos_inf; | |
2727 | else | |
2728 | i_ = neg_inf; | |
2729 | return *this; | |
2730 | } | |
2731 | switch (i_) | |
2732 | { | |
2733 | case 0: | |
2734 | case nan: | |
2735 | return *this; | |
2736 | case pos_inf: | |
2737 | case neg_inf: | |
2738 | if (x.i_ < 0) | |
2739 | i_ = -i_; | |
2740 | return *this; | |
2741 | } | |
2742 | i_ /= x.i_; | |
2743 | return *this; | |
2744 | } | |
2745 | ||
2746 | template <class I> | |
2747 | saturate<I>& | |
2748 | saturate<I>::operator%=(saturate x) | |
2749 | { | |
2750 | <font color="#c80000">// *this -= *this / x * x; // definition</font> | |
2751 | switch (x.i_) | |
2752 | { | |
2753 | case nan: | |
2754 | case neg_inf: | |
2755 | case 0: | |
2756 | case pos_inf: | |
2757 | i_ = nan; | |
2758 | return *this; | |
2759 | } | |
2760 | switch (i_) | |
2761 | { | |
2762 | case neg_inf: | |
2763 | case pos_inf: | |
2764 | i_ = nan; | |
2765 | case nan: | |
2766 | return *this; | |
2767 | } | |
2768 | i_ %= x.i_; | |
2769 | return *this; | |
2770 | } | |
2771 | ||
2772 | <font color="#c80000">// Demo overflow-safe integral durations ranging from picoseconds resolution to millennium resolution</font> | |
2773 | typedef std::datetime::duration<saturate<long long>, std::pico > picoseconds; | |
2774 | typedef std::datetime::duration<saturate<long long>, std::nano > nanoseconds; | |
2775 | typedef std::datetime::duration<saturate<long long>, std::micro > microseconds; | |
2776 | typedef std::datetime::duration<saturate<long long>, std::milli > milliseconds; | |
2777 | typedef std::datetime::duration<saturate<long long> > seconds; | |
2778 | typedef std::datetime::duration<saturate<long long>, std::ratio< 60LL> > minutes; | |
2779 | typedef std::datetime::duration<saturate<long long>, std::ratio< 3600LL> > hours; | |
2780 | typedef std::datetime::duration<saturate<long long>, std::ratio< 86400LL> > days; | |
2781 | typedef std::datetime::duration<saturate<long long>, std::ratio< 31556952LL> > years; | |
2782 | typedef std::datetime::duration<saturate<long long>, std::ratio<31556952000LL> > millennium; | |
2783 | ||
2784 | } <font color="#c80000">// User2</font> | |
2785 | ||
2786 | <font color="#c80000">// Demonstrate custom promotion rules (needed only if there are no implicit conversions)</font> | |
2787 | namespace User2 { namespace detail { | |
2788 | ||
2789 | template <class T1, class T2, bool = tmp::is_integral<T1>::value> | |
2790 | struct promote_helper; | |
2791 | ||
2792 | template <class T1, class T2> | |
2793 | struct promote_helper<T1, saturate<T2>, true> <font color="#c80000">// integral</font> | |
2794 | { | |
2795 | typedef typename std::common_type<T1, T2>::type rep; | |
2796 | typedef User2::saturate<rep> type; | |
2797 | }; | |
2798 | ||
2799 | template <class T1, class T2> | |
2800 | struct promote_helper<T1, saturate<T2>, false> <font color="#c80000">// floating</font> | |
2801 | { | |
2802 | typedef T1 type; | |
2803 | }; | |
2804 | ||
2805 | } } | |
2806 | ||
2807 | namespace std | |
2808 | { | |
2809 | ||
2810 | template <class T1, class T2> | |
2811 | struct common_type<User2::saturate<T1>, User2::saturate<T2> > | |
2812 | { | |
2813 | typedef typename common_type<T1, T2>::type rep; | |
2814 | typedef User2::saturate<rep> type; | |
2815 | }; | |
2816 | ||
2817 | template <class T1, class T2> | |
2818 | struct common_type<T1, User2::saturate<T2> > | |
2819 | : User2::detail::promote_helper<T1, User2::saturate<T2> > {}; | |
2820 | ||
2821 | template <class T1, class T2> | |
2822 | struct common_type<User2::saturate<T1>, T2> | |
2823 | : User2::detail::promote_helper<T2, User2::saturate<T1> > {}; | |
2824 | ||
2825 | ||
2826 | <font color="#c80000">// Demonstrate specialization of duration_values:</font> | |
2827 | ||
2828 | namespace datetime { | |
2829 | ||
2830 | template <class I> | |
2831 | struct duration_values<User2::saturate<I> > | |
2832 | { | |
2833 | typedef User2::saturate<I> Rep; | |
2834 | public: | |
2835 | static Rep zero() {return Rep(0);} | |
2836 | static Rep max() {return Rep(Rep::pos_inf-1);} | |
2837 | static Rep min() {return -max();} | |
2838 | }; | |
2839 | ||
2840 | } | |
2841 | ||
2842 | } | |
2843 | ||
2844 | #include <iostream> | |
2845 | ||
2846 | void testUser2() | |
2847 | { | |
2848 | std::cout << "*************\n"; | |
2849 | std::cout << "* testUser2 *\n"; | |
2850 | std::cout << "*************\n"; | |
2851 | using namespace User2; | |
2852 | typedef seconds::rep sat; | |
2853 | years yr(sat(100)); | |
2854 | std::cout << "100 years expressed as years = " << yr.count() << '\n'; | |
2855 | nanoseconds ns = yr; | |
2856 | std::cout << "100 years expressed as nanoseconds = " << ns.count() << '\n'; | |
2857 | ns += yr; | |
2858 | std::cout << "200 years expressed as nanoseconds = " << ns.count() << '\n'; | |
2859 | ns += yr; | |
2860 | std::cout << "300 years expressed as nanoseconds = " << ns.count() << '\n'; | |
2861 | <font color="#c80000">// yr = ns; // does not compile</font> | |
2862 | std::cout << "yr = ns; <font color="#c80000">// does not compile\n";</font> | |
2863 | <font color="#c80000">// picoseconds ps1 = yr; // does not compile, compile-time overflow in ratio arithmetic</font> | |
2864 | std::cout << "ps = yr; <font color="#c80000">// does not compile\n";</font> | |
2865 | ns = yr; | |
2866 | picoseconds ps = ns; | |
2867 | std::cout << "100 years expressed as picoseconds = " << ps.count() << '\n'; | |
2868 | ps = ns / sat(1000); | |
2869 | std::cout << "0.1 years expressed as picoseconds = " << ps.count() << '\n'; | |
2870 | yr = years(sat(-200000000)); | |
2871 | std::cout << "200 million years ago encoded in years: " << yr.count() << '\n'; | |
2872 | days d = std::datetime::duration_cast<days>(yr); | |
2873 | std::cout << "200 million years ago encoded in days: " << d.count() << '\n'; | |
2874 | millennium c = std::datetime::duration_cast<millennium>(yr); | |
2875 | std::cout << "200 million years ago encoded in millennium: " << c.count() << '\n'; | |
2876 | std::cout << "Demonstrate \"uninitialized protection\" behavior:\n"; | |
2877 | seconds sec; | |
2878 | for (++sec; sec < seconds(sat(10)); ++sec) | |
2879 | ; | |
2880 | std::cout << sec.count() << '\n'; | |
2881 | std::cout << "\n"; | |
2882 | } | |
2883 | ||
2884 | void testStdUser() | |
2885 | { | |
2886 | std::cout << "***************\n"; | |
2887 | std::cout << "* testStdUser *\n"; | |
2888 | std::cout << "***************\n"; | |
2889 | using namespace std::datetime; | |
2890 | hours hr = hours(100); | |
2891 | std::cout << "100 hours expressed as hours = " << hr.count() << '\n'; | |
2892 | nanoseconds ns = hr; | |
2893 | std::cout << "100 hours expressed as nanoseconds = " << ns.count() << '\n'; | |
2894 | ns += hr; | |
2895 | std::cout << "200 hours expressed as nanoseconds = " << ns.count() << '\n'; | |
2896 | ns += hr; | |
2897 | std::cout << "300 hours expressed as nanoseconds = " << ns.count() << '\n'; | |
2898 | <font color="#c80000">// hr = ns; // does not compile</font> | |
2899 | std::cout << "hr = ns; <font color="#c80000">// does not compile\n";</font> | |
2900 | <font color="#c80000">// hr * ns; // does not compile</font> | |
2901 | std::cout << "hr * ns; <font color="#c80000">// does not compile\n";</font> | |
2902 | duration<double> fs(2.5); | |
2903 | std::cout << "duration<double> has count() = " << fs.count() << '\n'; | |
2904 | <font color="#c80000">// seconds sec = fs; // does not compile</font> | |
2905 | std::cout << "seconds sec = duration<double> won't compile\n"; | |
2906 | seconds sec = duration_cast<seconds>(fs); | |
2907 | std::cout << "seconds has count() = " << sec.count() << '\n'; | |
2908 | std::cout << "\n"; | |
2909 | } | |
2910 | ||
2911 | <font color="#c80000">// timeval clock demo</font> | |
2912 | <font color="#c80000">// Demonstrate the use of a timeval-like struct to be used as the representation</font> | |
2913 | <font color="#c80000">// type for both duraiton and time_point.</font> | |
2914 | ||
2915 | namespace timeval_demo | |
2916 | { | |
2917 | ||
2918 | class xtime { | |
2919 | private: | |
2920 | long tv_sec; | |
2921 | long tv_usec; | |
2922 | ||
2923 | void fixup() { | |
2924 | if (tv_usec < 0) { | |
2925 | tv_usec += 1000000; | |
2926 | --tv_sec; | |
2927 | } | |
2928 | } | |
2929 | ||
2930 | public: | |
2931 | ||
2932 | explicit xtime(long sec, long usec) { | |
2933 | tv_sec = sec; | |
2934 | tv_usec = usec; | |
2935 | if (tv_usec < 0 || tv_usec >= 1000000) { | |
2936 | tv_sec += tv_usec / 1000000; | |
2937 | tv_usec %= 1000000; | |
2938 | fixup(); | |
2939 | } | |
2940 | } | |
2941 | ||
2942 | explicit xtime(long long usec) | |
2943 | { | |
2944 | tv_usec = static_cast<long>(usec % 1000000); | |
2945 | tv_sec = static_cast<long>(usec / 1000000); | |
2946 | fixup(); | |
2947 | } | |
2948 | ||
2949 | <font color="#c80000">// explicit</font> | |
2950 | operator long long() const {return static_cast<long long>(tv_sec) * 1000000 + tv_usec;} | |
2951 | ||
2952 | xtime& operator += (xtime rhs) { | |
2953 | tv_sec += rhs.tv_sec; | |
2954 | tv_usec += rhs.tv_usec; | |
2955 | if (tv_usec >= 1000000) { | |
2956 | tv_usec -= 1000000; | |
2957 | ++tv_sec; | |
2958 | } | |
2959 | return *this; | |
2960 | } | |
2961 | ||
2962 | xtime& operator -= (xtime rhs) { | |
2963 | tv_sec -= rhs.tv_sec; | |
2964 | tv_usec -= rhs.tv_usec; | |
2965 | fixup(); | |
2966 | return *this; | |
2967 | } | |
2968 | ||
2969 | xtime& operator %= (xtime rhs) { | |
2970 | long long t = tv_sec * 1000000 + tv_usec; | |
2971 | long long r = rhs.tv_sec * 1000000 + rhs.tv_usec; | |
2972 | t %= r; | |
2973 | tv_sec = t / 1000000; | |
2974 | tv_usec = t % 1000000; | |
2975 | fixup(); | |
2976 | return *this; | |
2977 | } | |
2978 | ||
2979 | friend xtime operator+(xtime x, xtime y) {return x += y;} | |
2980 | friend xtime operator-(xtime x, xtime y) {return x -= y;} | |
2981 | friend xtime operator%(xtime x, xtime y) {return x %= y;} | |
2982 | ||
2983 | friend bool operator==(xtime x, xtime y) | |
2984 | { return (x.tv_sec == y.tv_sec && x.tv_usec == y.tv_usec); } | |
2985 | ||
2986 | friend bool operator<(xtime x, xtime y) { | |
2987 | if (x.tv_sec == y.tv_sec) | |
2988 | return (x.tv_usec < y.tv_usec); | |
2989 | return (x.tv_sec < y.tv_sec); | |
2990 | } | |
2991 | ||
2992 | friend bool operator!=(xtime x, xtime y) { return !(x == y); } | |
2993 | friend bool operator> (xtime x, xtime y) { return y < x; } | |
2994 | friend bool operator<=(xtime x, xtime y) { return !(y < x); } | |
2995 | friend bool operator>=(xtime x, xtime y) { return !(x < y); } | |
2996 | ||
2997 | friend std::ostream& operator<<(std::ostream& os, xtime x) | |
2998 | {return os << '{' << x.tv_sec << ',' << x.tv_usec << '}';} | |
2999 | }; | |
3000 | ||
3001 | class xtime_clock | |
3002 | { | |
3003 | public: | |
3004 | typedef xtime rep; | |
3005 | typedef std::micro period; | |
3006 | typedef std::datetime::duration<rep, period> duration; | |
3007 | typedef std::datetime::time_point<xtime_clock> time_point; | |
3008 | ||
3009 | static time_point now(); | |
3010 | }; | |
3011 | ||
3012 | xtime_clock::time_point | |
3013 | xtime_clock::now() | |
3014 | { | |
3015 | time_point t(duration(xtime(0))); | |
3016 | gettimeofday((timeval*)&t, 0); | |
3017 | return t; | |
3018 | } | |
3019 | ||
3020 | void test_xtime_clock() | |
3021 | { | |
3022 | using namespace std::datetime; | |
3023 | std::cout << "timeval_demo system clock test\n"; | |
3024 | std::cout << "sizeof xtime_clock::time_point = " << sizeof(xtime_clock::time_point) << '\n'; | |
3025 | std::cout << "sizeof xtime_clock::duration = " << sizeof(xtime_clock::duration) << '\n'; | |
3026 | std::cout << "sizeof xtime_clock::rep = " << sizeof(xtime_clock::rep) << '\n'; | |
3027 | xtime_clock::duration delay(milliseconds(5)); | |
3028 | xtime_clock::time_point start = xtime_clock::now(); | |
3029 | while (xtime_clock::now() - start <= delay) | |
3030 | ; | |
3031 | xtime_clock::time_point stop = xtime_clock::now(); | |
3032 | xtime_clock::duration elapsed = stop - start; | |
3033 | std::cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n"; | |
3034 | } | |
3035 | ||
3036 | } <font color="#c80000">// timeval_demo</font> | |
3037 | ||
3038 | <font color="#c80000">// Handle duration with resolution not known until run time</font> | |
3039 | ||
3040 | namespace runtime_resolution | |
3041 | { | |
3042 | ||
3043 | class duration | |
3044 | { | |
3045 | public: | |
3046 | typedef long long rep; | |
3047 | private: | |
3048 | rep rep_; | |
3049 | ||
3050 | static const double ticks_per_nanosecond; | |
3051 | ||
3052 | public: | |
3053 | typedef std::datetime::duration<double, std::nano> tonanosec; | |
3054 | ||
3055 | duration() {} <font color="#c80000">// = default;</font> | |
3056 | explicit duration(const rep& r) : rep_(r) {} | |
3057 | ||
3058 | <font color="#c80000">// conversions</font> | |
3059 | explicit duration(const tonanosec& d) | |
3060 | : rep_(static_cast<rep>(d.count() * ticks_per_nanosecond)) {} | |
3061 | ||
3062 | <font color="#c80000">// explicit</font> | |
3063 | operator tonanosec() const {return tonanosec(rep_/ticks_per_nanosecond);} | |
3064 | ||
3065 | <font color="#c80000">// observer</font> | |
3066 | ||
3067 | rep count() const {return rep_;} | |
3068 | ||
3069 | <font color="#c80000">// arithmetic</font> | |
3070 | ||
3071 | duration& operator+=(const duration& d) {rep_ += d.rep_; return *this;} | |
3072 | duration& operator-=(const duration& d) {rep_ += d.rep_; return *this;} | |
3073 | duration& operator*=(rep rhs) {rep_ *= rhs; return *this;} | |
3074 | duration& operator/=(rep rhs) {rep_ /= rhs; return *this;} | |
3075 | ||
3076 | duration operator+() const {return *this;} | |
3077 | duration operator-() const {return duration(-rep_);} | |
3078 | duration& operator++() {++rep_; return *this;} | |
3079 | duration operator++(int) {return duration(rep_++);} | |
3080 | duration& operator--() {--rep_; return *this;} | |
3081 | duration operator--(int) {return duration(rep_--);} | |
3082 | ||
3083 | friend duration operator+(duration x, duration y) {return x += y;} | |
3084 | friend duration operator-(duration x, duration y) {return x -= y;} | |
3085 | friend duration operator*(duration x, rep y) {return x *= y;} | |
3086 | friend duration operator*(rep x, duration y) {return y *= x;} | |
3087 | friend duration operator/(duration x, rep y) {return x /= y;} | |
3088 | ||
3089 | friend bool operator==(duration x, duration y) {return x.rep_ == y.rep_;} | |
3090 | friend bool operator!=(duration x, duration y) {return !(x == y);} | |
3091 | friend bool operator< (duration x, duration y) {return x.rep_ < y.rep_;} | |
3092 | friend bool operator<=(duration x, duration y) {return !(y < x);} | |
3093 | friend bool operator> (duration x, duration y) {return y < x;} | |
3094 | friend bool operator>=(duration x, duration y) {return !(x < y);} | |
3095 | }; | |
3096 | ||
3097 | static | |
3098 | double | |
3099 | init_duration() | |
3100 | { | |
3101 | mach_timebase_info_data_t MachInfo; | |
3102 | mach_timebase_info(&MachInfo); | |
3103 | return static_cast<double>(MachInfo.denom) / MachInfo.numer; | |
3104 | } | |
3105 | ||
3106 | const double duration::ticks_per_nanosecond = init_duration(); | |
3107 | ||
3108 | class clock; | |
3109 | ||
3110 | class time_point | |
3111 | { | |
3112 | public: | |
3113 | typedef runtime_resolution::clock clock; | |
3114 | typedef long long rep; | |
3115 | private: | |
3116 | rep rep_; | |
3117 | ||
3118 | ||
3119 | rep count() const {return rep_;} | |
3120 | public: | |
3121 | ||
3122 | time_point() : rep_(0) {} | |
3123 | explicit time_point(const duration& d) | |
3124 | : rep_(d.count()) {} | |
3125 | ||
3126 | <font color="#c80000">// arithmetic</font> | |
3127 | ||
3128 | time_point& operator+=(const duration& d) {rep_ += d.count(); return *this;} | |
3129 | time_point& operator-=(const duration& d) {rep_ -= d.count(); return *this;} | |
3130 | ||
3131 | friend time_point operator+(time_point x, duration y) {return x += y;} | |
3132 | friend time_point operator+(duration x, time_point y) {return y += x;} | |
3133 | friend time_point operator-(time_point x, duration y) {return x -= y;} | |
3134 | friend duration operator-(time_point x, time_point y) {return duration(x.rep_ - y.rep_);} | |
3135 | }; | |
3136 | ||
3137 | class clock | |
3138 | { | |
3139 | public: | |
3140 | typedef duration::rep rep; | |
3141 | typedef runtime_resolution::duration duration; | |
3142 | typedef runtime_resolution::time_point time_point; | |
3143 | ||
3144 | static time_point now() {return time_point(duration(mach_absolute_time()));} | |
3145 | }; | |
3146 | ||
3147 | void test() | |
3148 | { | |
3149 | using namespace std::datetime; | |
3150 | std::cout << "runtime_resolution test\n"; | |
3151 | clock::duration delay(std::datetime::milliseconds(5)); | |
3152 | clock::time_point start = clock::now(); | |
3153 | while (clock::now() - start <= delay) | |
3154 | ; | |
3155 | clock::time_point stop = clock::now(); | |
3156 | clock::duration elapsed = stop - start; | |
3157 | std::cout << "paused " << nanoseconds(duration_cast<nanoseconds>(duration::tonanosec(elapsed))).count() | |
3158 | << " nanoseconds\n"; | |
3159 | } | |
3160 | ||
3161 | } <font color="#c80000">// runtime_resolution</font> | |
3162 | ||
3163 | <font color="#c80000">// miscellaneous tests and demos:</font> | |
3164 | ||
3165 | #include <cassert> | |
3166 | #include <iostream> | |
3167 | ||
3168 | using namespace std::datetime; | |
3169 | ||
3170 | void physics_function(duration<double> d) | |
3171 | { | |
3172 | std::cout << "d = " << d.count() << '\n'; | |
3173 | } | |
3174 | ||
3175 | void drive_physics_function() | |
3176 | { | |
3177 | physics_function(nanoseconds(3)); | |
3178 | physics_function(hours(3)); | |
3179 | physics_function(duration<double>(2./3)); | |
3180 | std::cout.precision(16); | |
3181 | physics_function( hours(3) + nanoseconds(-3) ); | |
3182 | } | |
3183 | ||
3184 | void test_range() | |
3185 | { | |
3186 | using namespace std::datetime; | |
3187 | hours h1 = hours(24 * ( 365 * 292 + 292/4)); | |
3188 | nanoseconds n1 = h1 + nanoseconds(1); | |
3189 | nanoseconds delta = n1 - h1; | |
3190 | std::cout << "292 years of hours = " << h1.count() << "hr\n"; | |
3191 | std::cout << "Add a nanosecond = " << n1.count() << "ns\n"; | |
3192 | std::cout << "Find the difference = " << delta.count() << "ns\n"; | |
3193 | } | |
3194 | ||
3195 | void test_extended_range() | |
3196 | { | |
3197 | using namespace std::datetime; | |
3198 | hours h1 = hours(24 * ( 365 * 244000 + 244000/4)); | |
3199 | <font color="#c80000">/*auto*/</font> microseconds u1 = h1 + microseconds(1); | |
3200 | <font color="#c80000">/*auto*/</font> microseconds delta = u1 - h1; | |
3201 | std::cout << "244,000 years of hours = " << h1.count() << "hr\n"; | |
3202 | std::cout << "Add a microsecond = " << u1.count() << "us\n"; | |
3203 | std::cout << "Find the difference = " << delta.count() << "us\n"; | |
3204 | } | |
3205 | ||
3206 | template <class Rep, class Period> | |
3207 | void inspect_duration(std::datetime::duration<Rep, Period> d, const std::string& name) | |
3208 | { | |
3209 | typedef std::datetime::duration<Rep, Period> Duration; | |
3210 | std::cout << "********* " << name << " *********\n"; | |
3211 | std::cout << "The period of " << name << " is " << (double)Period::num/Period::den << " seconds.\n"; | |
3212 | std::cout << "The frequency of " << name << " is " << (double)Period::den/Period::num << " Hz.\n"; | |
3213 | std::cout << "The representation is "; | |
3214 | if (tmp::is_floating_point<Rep>::value) | |
3215 | { | |
3216 | std::cout << "floating point\n"; | |
3217 | std::cout << "The precision is the most significant "; | |
3218 | std::cout << std::numeric_limits<Rep>::digits10 << " decimal digits.\n"; | |
3219 | } | |
3220 | else if (tmp::is_integral<Rep>::value) | |
3221 | { | |
3222 | std::cout << "integral\n"; | |
3223 | d = Duration(Rep(1)); | |
3224 | std::datetime::duration<double> dsec = d; | |
3225 | std::cout << "The precision is " << dsec.count() << " seconds.\n"; | |
3226 | } | |
3227 | else | |
3228 | { | |
3229 | std::cout << "a class type\n"; | |
3230 | d = Duration(Rep(1)); | |
3231 | std::datetime::duration<double> dsec = d; | |
3232 | std::cout << "The precision is " << dsec.count() << " seconds.\n"; | |
3233 | } | |
3234 | d = Duration(std::numeric_limits<Rep>::max()); | |
3235 | using namespace std::datetime; | |
3236 | using namespace std; | |
3237 | typedef duration<double, ratio_multiply<ratio<24*3652425,10000>, hours::period>::type> Years; | |
3238 | Years years = d; | |
3239 | std::cout << "The range is +/- " << years.count() << " years.\n"; | |
3240 | std::cout << "sizeof(" << name << ") = " << sizeof(d) << '\n'; | |
3241 | } | |
3242 | ||
3243 | void inspect_all() | |
3244 | { | |
3245 | using namespace std::datetime; | |
3246 | std::cout.precision(6); | |
3247 | inspect_duration(nanoseconds(), "nanoseconds"); | |
3248 | inspect_duration(microseconds(), "microseconds"); | |
3249 | inspect_duration(milliseconds(), "milliseconds"); | |
3250 | inspect_duration(seconds(), "seconds"); | |
3251 | inspect_duration(minutes(), "minutes"); | |
3252 | inspect_duration(hours(), "hours"); | |
3253 | inspect_duration(duration<double>(), "duration<double>"); | |
3254 | } | |
3255 | ||
3256 | void test_milliseconds() | |
3257 | { | |
3258 | using namespace std::datetime; | |
3259 | milliseconds ms(250); | |
3260 | ms += milliseconds(1); | |
3261 | milliseconds ms2(150); | |
3262 | milliseconds msdiff = ms - ms2; | |
3263 | if (msdiff == milliseconds(101)) | |
3264 | std::cout << "success\n"; | |
3265 | else | |
3266 | std::cout << "failure: " << msdiff.count() << '\n'; | |
3267 | } | |
3268 | ||
3269 | using namespace std; | |
3270 | using namespace std::datetime; | |
3271 | ||
3272 | <font color="#c80000">// Example round_up utility: converts d to To, rounding up for inexact conversions</font> | |
3273 | <font color="#c80000">// Being able to *easily* write this function is a major feature!</font> | |
3274 | template <class To, class Rep, class Period> | |
3275 | To | |
3276 | round_up(duration<Rep, Period> d) | |
3277 | { | |
3278 | To result = duration_cast<To>(d); | |
3279 | if (result < d) | |
3280 | ++result; | |
3281 | return result; | |
3282 | } | |
3283 | ||
3284 | <font color="#c80000">// demonstrate interaction with xtime-like facility:</font> | |
3285 | ||
3286 | using namespace std::datetime; | |
3287 | ||
3288 | struct xtime | |
3289 | { | |
3290 | long sec; | |
3291 | unsigned long usec; | |
3292 | }; | |
3293 | ||
3294 | template <class Rep, class Period> | |
3295 | xtime | |
3296 | to_xtime_truncate(duration<Rep, Period> d) | |
3297 | { | |
3298 | xtime xt; | |
3299 | xt.sec = duration_cast<seconds>(d).count(); | |
3300 | xt.usec = duration_cast<microseconds>(d - seconds(xt.sec)).count(); | |
3301 | return xt; | |
3302 | } | |
3303 | ||
3304 | template <class Rep, class Period> | |
3305 | xtime | |
3306 | to_xtime_round_up(duration<Rep, Period> d) | |
3307 | { | |
3308 | xtime xt; | |
3309 | xt.sec = duration_cast<seconds>(d).count(); | |
3310 | xt.usec = round_up<microseconds>(d - seconds(xt.sec)).count(); | |
3311 | return xt; | |
3312 | } | |
3313 | ||
3314 | microseconds | |
3315 | from_xtime(xtime xt) | |
3316 | { | |
3317 | return seconds(xt.sec) + microseconds(xt.usec); | |
3318 | } | |
3319 | ||
3320 | void print(xtime xt) | |
3321 | { | |
3322 | cout << '{' << xt.sec << ',' << xt.usec << "}\n"; | |
3323 | } | |
3324 | ||
3325 | void test_with_xtime() | |
3326 | { | |
3327 | cout << "test_with_xtime\n"; | |
3328 | xtime xt = to_xtime_truncate(seconds(3) + milliseconds(251)); | |
3329 | print(xt); | |
3330 | milliseconds ms = duration_cast<milliseconds>(from_xtime(xt)); | |
3331 | cout << ms.count() << " milliseconds\n"; | |
3332 | xt = to_xtime_round_up(ms); | |
3333 | print(xt); | |
3334 | xt = to_xtime_truncate(seconds(3) + nanoseconds(999)); | |
3335 | print(xt); | |
3336 | xt = to_xtime_round_up(seconds(3) + nanoseconds(999)); | |
3337 | print(xt); | |
3338 | } | |
3339 | ||
3340 | void test_system_clock() | |
3341 | { | |
3342 | cout << "system_clock test" << endl; | |
3343 | system_clock::duration delay = milliseconds(5); | |
3344 | system_clock::time_point start = system_clock::now(); | |
3345 | while (system_clock::now() - start <= delay) | |
3346 | ; | |
3347 | system_clock::time_point stop = system_clock::now(); | |
3348 | system_clock::duration elapsed = stop - start; | |
3349 | cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n"; | |
3350 | start = system_clock::now(); | |
3351 | stop = system_clock::now(); | |
3352 | cout << "system_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n"; | |
3353 | } | |
3354 | ||
3355 | void test_monotonic_clock() | |
3356 | { | |
3357 | cout << "monotonic_clock test" << endl; | |
3358 | monotonic_clock::duration delay = milliseconds(5); | |
3359 | monotonic_clock::time_point start = monotonic_clock::now(); | |
3360 | while (monotonic_clock::now() - start <= delay) | |
3361 | ; | |
3362 | monotonic_clock::time_point stop = monotonic_clock::now(); | |
3363 | monotonic_clock::duration elapsed = stop - start; | |
3364 | cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n"; | |
3365 | start = monotonic_clock::now(); | |
3366 | stop = monotonic_clock::now(); | |
3367 | cout << "monotonic_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n"; | |
3368 | } | |
3369 | ||
3370 | void test_hi_resolution_clock() | |
3371 | { | |
3372 | cout << "high_resolution_clock test" << endl; | |
3373 | high_resolution_clock::duration delay = milliseconds(5); | |
3374 | high_resolution_clock::time_point start = high_resolution_clock::now(); | |
3375 | while (high_resolution_clock::now() - start <= delay) | |
3376 | ; | |
3377 | high_resolution_clock::time_point stop = high_resolution_clock::now(); | |
3378 | high_resolution_clock::duration elapsed = stop - start; | |
3379 | cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n"; | |
3380 | start = high_resolution_clock::now(); | |
3381 | stop = high_resolution_clock::now(); | |
3382 | cout << "high_resolution_clock resolution estimate: " << nanoseconds(stop-start).count() << " nanoseconds\n"; | |
3383 | } | |
3384 | ||
3385 | void test_mixed_clock() | |
3386 | { | |
3387 | cout << "mixed clock test" << endl; | |
3388 | high_resolution_clock::time_point hstart = high_resolution_clock::now(); | |
3389 | cout << "Add 5 milliseconds to a high_resolution_clock::time_point\n"; | |
3390 | monotonic_clock::time_point mend = hstart + milliseconds(5); | |
3391 | bool b = hstart == mend; | |
3392 | system_clock::time_point sstart = system_clock::now(); | |
3393 | std::cout << "Subtracting system_clock::time_point from monotonic_clock::time_point doesn't compile\n"; | |
3394 | <font color="#c80000">// mend - sstart; // doesn't compile</font> | |
3395 | cout << "subtract high_resolution_clock::time_point from monotonic_clock::time_point" | |
3396 | " and add that to a system_clock::time_point\n"; | |
3397 | system_clock::time_point send = sstart + duration_cast<system_clock::duration>(mend - hstart); | |
3398 | cout << "subtract two system_clock::time_point's and output that in microseconds:\n"; | |
3399 | microseconds ms = send - sstart; | |
3400 | cout << ms.count() << " microseconds\n"; | |
3401 | } | |
3402 | ||
3403 | void test_c_mapping() | |
3404 | { | |
3405 | cout << "C map test\n"; | |
3406 | using namespace std::datetime; | |
3407 | system_clock::time_point t1 = system_clock::now(); | |
3408 | std::time_t c_time = system_clock::to_time_t(t1); | |
3409 | std::tm* tmptr = std::localtime(&c_time); | |
3410 | std::cout << "It is now " << tmptr->tm_hour << ':' << tmptr->tm_min << ':' << tmptr->tm_sec << ' ' | |
3411 | << tmptr->tm_year + 1900 << '-' << tmptr->tm_mon + 1 << '-' << tmptr->tm_mday << '\n'; | |
3412 | c_time = std::mktime(tmptr); | |
3413 | system_clock::time_point t2 = system_clock::from_time_t(c_time); | |
3414 | microseconds ms = t1 - t2; | |
3415 | std::cout << "Round-tripping through the C interface truncated the precision by " << ms.count() << " microseconds\n"; | |
3416 | } | |
3417 | ||
3418 | void test_duration_division() | |
3419 | { | |
3420 | cout << hours(3) / milliseconds(5) << '\n'; | |
3421 | cout << milliseconds(5) / hours(3) << '\n'; | |
3422 | cout << hours(1) / milliseconds(1) << '\n'; | |
3423 | } | |
3424 | ||
3425 | namespace I_dont_like_the_default_duration_behavior | |
3426 | { | |
3427 | ||
3428 | <font color="#c80000">// Here's how you override the duration's default constructor to do anything you want (in this case zero)</font> | |
3429 | ||
3430 | template <class R> | |
3431 | class zero_default | |
3432 | { | |
3433 | public: | |
3434 | typedef R rep; | |
3435 | ||
3436 | private: | |
3437 | rep rep_; | |
3438 | public: | |
3439 | zero_default(rep i = 0) : rep_(i) {} | |
3440 | operator rep() const {return rep_;} | |
3441 | ||
3442 | zero_default& operator+=(zero_default x) {rep_ += x.rep_; return *this;} | |
3443 | zero_default& operator-=(zero_default x) {rep_ -= x.rep_; return *this;} | |
3444 | zero_default& operator*=(zero_default x) {rep_ *= x.rep_; return *this;} | |
3445 | zero_default& operator/=(zero_default x) {rep_ /= x.rep_; return *this;} | |
3446 | ||
3447 | zero_default operator+ () const {return *this;} | |
3448 | zero_default operator- () const {return zero_default(-rep_);} | |
3449 | zero_default& operator++() {++rep_; return *this;} | |
3450 | zero_default operator++(int) {return zero_default(rep_++);} | |
3451 | zero_default& operator--() {--rep_; return *this;} | |
3452 | zero_default operator--(int) {return zero_default(rep_--);} | |
3453 | ||
3454 | friend zero_default operator+(zero_default x, zero_default y) {return x += y;} | |
3455 | friend zero_default operator-(zero_default x, zero_default y) {return x -= y;} | |
3456 | friend zero_default operator*(zero_default x, zero_default y) {return x *= y;} | |
3457 | friend zero_default operator/(zero_default x, zero_default y) {return x /= y;} | |
3458 | ||
3459 | friend bool operator==(zero_default x, zero_default y) {return x.rep_ == y.rep_;} | |
3460 | friend bool operator!=(zero_default x, zero_default y) {return !(x == y);} | |
3461 | friend bool operator< (zero_default x, zero_default y) {return x.rep_ < y.rep_;} | |
3462 | friend bool operator<=(zero_default x, zero_default y) {return !(y < x);} | |
3463 | friend bool operator> (zero_default x, zero_default y) {return y < x;} | |
3464 | friend bool operator>=(zero_default x, zero_default y) {return !(x < y);} | |
3465 | }; | |
3466 | ||
3467 | typedef std::datetime::duration<zero_default<long long>, std::nano > nanoseconds; | |
3468 | typedef std::datetime::duration<zero_default<long long>, std::micro > microseconds; | |
3469 | typedef std::datetime::duration<zero_default<long long>, std::milli > milliseconds; | |
3470 | typedef std::datetime::duration<zero_default<long long> > seconds; | |
3471 | typedef std::datetime::duration<zero_default<long long>, std::ratio<60> > minutes; | |
3472 | typedef std::datetime::duration<zero_default<long long>, std::ratio<3600> > hours; | |
3473 | ||
3474 | void test() | |
3475 | { | |
3476 | milliseconds ms; | |
3477 | cout << ms.count() << '\n'; | |
3478 | } | |
3479 | ||
3480 | } <font color="#c80000">// I_dont_like_the_default_duration_behavior</font> | |
3481 | ||
3482 | <font color="#c80000">// Build a min for two time_points</font> | |
3483 | ||
3484 | template <class Rep, class Period> | |
3485 | void | |
3486 | print_duration(ostream& os, duration<Rep, Period> d) | |
3487 | { | |
3488 | os << d.count() << " * " << Period::num << '/' << Period::den << " seconds\n"; | |
3489 | } | |
3490 | ||
3491 | <font color="#c80000">// Example min utility: returns the earliest time_point</font> | |
3492 | <font color="#c80000">// Being able to *easily* write this function is a major feature!</font> | |
3493 | template <class Clock, class Duration1, class Duration2> | |
3494 | inline | |
3495 | typename common_type<time_point<Clock, Duration1>, time_point<Clock, Duration2> >::type | |
3496 | min(time_point<Clock, Duration1> t1, time_point<Clock, Duration2> t2) | |
3497 | { | |
3498 | return t2 < t1 ? t2 : t1; | |
3499 | } | |
3500 | ||
3501 | void test_min() | |
3502 | { | |
3503 | typedef time_point<system_clock, common_type<system_clock::duration, seconds>::type> T1; | |
3504 | typedef time_point<system_clock, common_type<system_clock::duration, nanoseconds>::type> T2; | |
3505 | typedef common_type<T1, T2>::type T3; | |
3506 | <font color="#c80000">/*auto*/</font> T1 t1 = system_clock::now() + seconds(3); | |
3507 | <font color="#c80000">/*auto*/</font> T2 t2 = system_clock::now() + nanoseconds(3); | |
3508 | <font color="#c80000">/*auto*/</font> T3 t3 = min(t1, t2); | |
3509 | print_duration(cout, t1 - t3); | |
3510 | print_duration(cout, t2 - t3); | |
3511 | } | |
3512 | ||
3513 | void explore_limits() | |
3514 | { | |
3515 | typedef duration<long long, ratio_multiply<ratio<24*3652425,10000>, hours::period>::type> Years; | |
3516 | monotonic_clock::time_point t1( Years(250)); | |
3517 | monotonic_clock::time_point t2(-Years(250)); | |
3518 | <font color="#c80000">// nanosecond resolution is likely to overflow. "up cast" to microseconds.</font> | |
3519 | <font color="#c80000">// The "up cast" trades precision for range.</font> | |
3520 | microseconds d = time_point_cast<microseconds>(t1) - time_point_cast<microseconds>(t2); | |
3521 | cout << d.count() << " microseconds\n"; | |
3522 | } | |
3523 | ||
3524 | void manipulate_clock_object(system_clock clock) | |
3525 | { | |
3526 | system_clock::duration delay = milliseconds(5); | |
3527 | system_clock::time_point start = clock.now(); | |
3528 | while (clock.now() - start <= delay) | |
3529 | ; | |
3530 | system_clock::time_point stop = clock.now(); | |
3531 | system_clock::duration elapsed = stop - start; | |
3532 | cout << "paused " << nanoseconds(elapsed).count() << " nanoseconds\n"; | |
3533 | }; | |
3534 | ||
3535 | template <long long speed> | |
3536 | struct cycle_count | |
3537 | { | |
3538 | typedef typename ratio_multiply<ratio<speed>, mega>::type frequency; <font color="#c80000">// Mhz</font> | |
3539 | typedef typename ratio_divide<ratio<1>, frequency>::type period; | |
3540 | typedef long long rep; | |
3541 | typedef std::datetime::duration<rep, period> duration; | |
3542 | typedef std::datetime::time_point<cycle_count> time_point; | |
3543 | ||
3544 | static time_point now() | |
3545 | { | |
3546 | static long long tick = 0; | |
3547 | <font color="#c80000">// return exact cycle count</font> | |
3548 | return time_point(duration(++tick)); <font color="#c80000">// fake access to clock cycle count</font> | |
3549 | } | |
3550 | }; | |
3551 | ||
3552 | template <long long speed> | |
3553 | struct approx_cycle_count | |
3554 | { | |
3555 | static const long long frequency = speed * 1000000; <font color="#c80000">// MHz</font> | |
3556 | typedef nanoseconds duration; | |
3557 | typedef duration::rep rep; | |
3558 | typedef duration::period period; | |
3559 | static const long long nanosec_per_sec = period::den; | |
3560 | typedef std::datetime::time_point<approx_cycle_count> time_point; | |
3561 | ||
3562 | static time_point now() | |
3563 | { | |
3564 | static long long tick = 0; | |
3565 | <font color="#c80000">// return cycle count as an approximate number of nanoseconds</font> | |
3566 | <font color="#c80000">// compute as if nanoseconds is only duration in the std::lib</font> | |
3567 | return time_point(duration(++tick * nanosec_per_sec / frequency)); | |
3568 | } | |
3569 | }; | |
3570 | ||
3571 | void cycle_count_delay() | |
3572 | { | |
3573 | { | |
3574 | typedef cycle_count<400> clock; | |
3575 | cout << "\nSimulated " << clock::frequency::num / mega::num << "MHz clock which has a tick period of " | |
3576 | << duration<double, nano>(clock::duration(1)).count() << " nanoseconds\n"; | |
3577 | nanoseconds delayns(500); | |
3578 | clock::duration delay = duration_cast<clock::duration>(delayns); | |
3579 | cout << "delay = " << delayns.count() << " nanoseconds which is " << delay.count() << " cycles\n"; | |
3580 | clock::time_point start = clock::now(); | |
3581 | clock::time_point stop = start + delay; | |
3582 | while (clock::now() < stop) <font color="#c80000">// no multiplies or divides in this loop</font> | |
3583 | ; | |
3584 | clock::time_point end = clock::now(); | |
3585 | clock::duration elapsed = end - start; | |
3586 | cout << "paused " << elapsed.count() << " cycles "; | |
3587 | cout << "which is " << duration_cast<nanoseconds>(elapsed).count() << " nanoseconds\n"; | |
3588 | } | |
3589 | { | |
3590 | typedef approx_cycle_count<400> clock; | |
3591 | cout << "\nSimulated " << clock::frequency / 1000000 << "MHz clock modeled with nanoseconds\n"; | |
3592 | clock::duration delay = nanoseconds(500); | |
3593 | cout << "delay = " << delay.count() << " nanoseconds\n"; | |
3594 | clock::time_point start = clock::now(); | |
3595 | clock::time_point stop = start + delay; | |
3596 | while (clock::now() < stop) <font color="#c80000">// 1 multiplication and 1 division in this loop</font> | |
3597 | ; | |
3598 | clock::time_point end = clock::now(); | |
3599 | clock::duration elapsed = end - start; | |
3600 | cout << "paused " << elapsed.count() << " nanoseconds\n"; | |
3601 | } | |
3602 | { | |
3603 | typedef cycle_count<1500> clock; | |
3604 | cout << "\nSimulated " << clock::frequency::num / mega::num << "MHz clock which has a tick period of " | |
3605 | << duration<double, nano>(clock::duration(1)).count() << " nanoseconds\n"; | |
3606 | nanoseconds delayns(500); | |
3607 | clock::duration delay = duration_cast<clock::duration>(delayns); | |
3608 | cout << "delay = " << delayns.count() << " nanoseconds which is " << delay.count() << " cycles\n"; | |
3609 | clock::time_point start = clock::now(); | |
3610 | clock::time_point stop = start + delay; | |
3611 | while (clock::now() < stop) <font color="#c80000">// no multiplies or divides in this loop</font> | |
3612 | ; | |
3613 | clock::time_point end = clock::now(); | |
3614 | clock::duration elapsed = end - start; | |
3615 | cout << "paused " << elapsed.count() << " cycles "; | |
3616 | cout << "which is " << duration_cast<nanoseconds>(elapsed).count() << " nanoseconds\n"; | |
3617 | } | |
3618 | { | |
3619 | typedef approx_cycle_count<1500> clock; | |
3620 | cout << "\nSimulated " << clock::frequency / 1000000 << "MHz clock modeled with nanoseconds\n"; | |
3621 | clock::duration delay = nanoseconds(500); | |
3622 | cout << "delay = " << delay.count() << " nanoseconds\n"; | |
3623 | clock::time_point start = clock::now(); | |
3624 | clock::time_point stop = start + delay; | |
3625 | while (clock::now() < stop) <font color="#c80000">// 1 multiplication and 1 division in this loop</font> | |
3626 | ; | |
3627 | clock::time_point end = clock::now(); | |
3628 | clock::duration elapsed = end - start; | |
3629 | cout << "paused " << elapsed.count() << " nanoseconds\n"; | |
3630 | } | |
3631 | } | |
3632 | ||
3633 | void test_special_values() | |
3634 | { | |
3635 | std::cout << "duration<unsigned>::min().count() = " << duration<unsigned>::min().count() << '\n'; | |
3636 | std::cout << "duration<unsigned>::zero().count() = " << duration<unsigned>::zero().count() << '\n'; | |
3637 | std::cout << "duration<unsigned>::max().count() = " << duration<unsigned>::max().count() << '\n'; | |
3638 | std::cout << "duration<int>::min().count() = " << duration<int>::min().count() << '\n'; | |
3639 | std::cout << "duration<int>::zero().count() = " << duration<int>::zero().count() << '\n'; | |
3640 | std::cout << "duration<int>::max().count() = " << duration<int>::max().count() << '\n'; | |
3641 | } | |
3642 | ||
3643 | int main() | |
3644 | { | |
3645 | basic_examples(); | |
3646 | testStdUser(); | |
3647 | testUser1(); | |
3648 | testUser2(); | |
3649 | drive_physics_function(); | |
3650 | test_range(); | |
3651 | test_extended_range(); | |
3652 | inspect_all(); | |
3653 | test_milliseconds(); | |
3654 | test_with_xtime(); | |
3655 | test_system_clock(); | |
3656 | test_monotonic_clock(); | |
3657 | test_hi_resolution_clock(); | |
3658 | test_mixed_clock(); | |
3659 | timeval_demo::test_xtime_clock(); | |
3660 | runtime_resolution::test(); | |
3661 | test_c_mapping(); | |
3662 | test_duration_division(); | |
3663 | I_dont_like_the_default_duration_behavior::test(); | |
3664 | test_min(); | |
3665 | #if VARIADIC_COMMON_TYPE | |
3666 | inspect_duration(common_type<duration<double>, hours, microseconds>::type(), | |
3667 | "common_type<duration<double>, hours, microseconds>::type"); | |
3668 | #endif | |
3669 | explore_limits(); | |
3670 | manipulate_clock_object(system_clock()); | |
3671 | duration<double, milli> d = milliseconds(3) * 2.5; | |
3672 | inspect_duration(milliseconds(3) * 2.5, "milliseconds(3) * 2.5"); | |
3673 | cout << d.count() << '\n'; | |
3674 | <font color="#c80000">// milliseconds ms(3.5); // doesn't compile</font> | |
3675 | cout << "milliseconds ms(3.5) doesn't compile\n"; | |
3676 | cycle_count_delay(); | |
3677 | test_special_values(); | |
3678 | } | |
3679 | ||
3680 | <font color="#c80000">/* | |
3681 | Output | |
3682 | ||
3683 | Running basic examples | |
3684 | sleep_for 3000000 microseconds | |
3685 | sleep_for 1 microseconds | |
3686 | sleep_until 10:47:17.728293 which is 4499340 microseconds away | |
3687 | try_lock_for 30000 microseconds | |
3688 | try_lock_until 10:47:17.728285 which is 4499303 microseconds away | |
3689 | wait_for 60000000 microseconds | |
3690 | wait_until 10:47:17.728285 which is 4499264 microseconds away | |
3691 | sleep_for 250000 microseconds | |
3692 | sleep_until 10:47:14.729077 which is 1499979 microseconds away | |
3693 | *************** | |
3694 | * testStdUser * | |
3695 | *************** | |
3696 | 100 hours expressed as hours = 100 | |
3697 | 100 hours expressed as nanoseconds = 360000000000000 | |
3698 | 200 hours expressed as nanoseconds = 720000000000000 | |
3699 | 300 hours expressed as nanoseconds = 1080000000000000 | |
3700 | hr = ns; <font color="#c80000">// does not compile</font> | |
3701 | hr * ns; <font color="#c80000">// does not compile</font> | |
3702 | duration<double> has count() = 2.5 | |
3703 | seconds sec = duration<double> won't compile | |
3704 | seconds has count() = 2 | |
3705 | ||
3706 | ************* | |
3707 | * testUser1 * | |
3708 | ************* | |
3709 | Speed = 24.5872 meters/sec | |
3710 | Acceleration = 9.81456 meters/sec^2 | |
3711 | Distance = 13.5204 meters | |
3712 | There are 125/201168 miles/meter which is approximately 0.000621371 | |
3713 | There are 201168/125 meters/mile which is approximately 1609.34 | |
3714 | 1 attosecond is 1e-18 seconds | |
3715 | sec = as; <font color="#c80000">// compiles</font> | |
3716 | 1 second is 1e+18 attoseconds | |
3717 | as = sec; <font color="#c80000">// compiles</font> | |
3718 | ||
3719 | ************* | |
3720 | * testUser2 * | |
3721 | ************* | |
3722 | 100 years expressed as years = 100 | |
3723 | 100 years expressed as nanoseconds = 3155695200000000000 | |
3724 | 200 years expressed as nanoseconds = 6311390400000000000 | |
3725 | 300 years expressed as nanoseconds = inf | |
3726 | yr = ns; <font color="#c80000">// does not compile</font> | |
3727 | ps = yr; <font color="#c80000">// does not compile</font> | |
3728 | 100 years expressed as picoseconds = inf | |
3729 | 0.1 years expressed as picoseconds = 3155695200000000000 | |
3730 | 200 million years ago encoded in years: -200000000 | |
3731 | 200 million years ago encoded in days: -73048500000 | |
3732 | 200 million years ago encoded in millennium: -200000 | |
3733 | Demonstrate "uninitialized protection" behavior: | |
3734 | nan | |
3735 | ||
3736 | d = 3e-09 | |
3737 | d = 10800 | |
3738 | d = 0.666667 | |
3739 | d = 10799.999999997 | |
3740 | 292 years of hours = 2559672hr | |
3741 | Add a nanosecond = 9214819200000000001ns | |
3742 | Find the difference = 1ns | |
3743 | 244,000 years of hours = 2138904000hr | |
3744 | Add a microsecond = 7700054400000000001us | |
3745 | Find the difference = 1us | |
3746 | ********* nanoseconds ********* | |
3747 | The period of nanoseconds is 1e-09 seconds. | |
3748 | The frequency of nanoseconds is 1e+09 Hz. | |
3749 | The representation is integral | |
3750 | The precision is 1e-09 seconds. | |
3751 | The range is +/- 292.277 years. | |
3752 | sizeof(nanoseconds) = 8 | |
3753 | ********* microseconds ********* | |
3754 | The period of microseconds is 1e-06 seconds. | |
3755 | The frequency of microseconds is 1e+06 Hz. | |
3756 | The representation is integral | |
3757 | The precision is 1e-06 seconds. | |
3758 | The range is +/- 292277 years. | |
3759 | sizeof(microseconds) = 8 | |
3760 | ********* milliseconds ********* | |
3761 | The period of milliseconds is 0.001 seconds. | |
3762 | The frequency of milliseconds is 1000 Hz. | |
3763 | The representation is integral | |
3764 | The precision is 0.001 seconds. | |
3765 | The range is +/- 2.92277e+08 years. | |
3766 | sizeof(milliseconds) = 8 | |
3767 | ********* seconds ********* | |
3768 | The period of seconds is 1 seconds. | |
3769 | The frequency of seconds is 1 Hz. | |
3770 | The representation is integral | |
3771 | The precision is 1 seconds. | |
3772 | The range is +/- 2.92277e+11 years. | |
3773 | sizeof(seconds) = 8 | |
3774 | ********* minutes ********* | |
3775 | The period of minutes is 60 seconds. | |
3776 | The frequency of minutes is 0.0166667 Hz. | |
3777 | The representation is integral | |
3778 | The precision is 60 seconds. | |
3779 | The range is +/- 4083.06 years. | |
3780 | sizeof(minutes) = 4 | |
3781 | ********* hours ********* | |
3782 | The period of hours is 3600 seconds. | |
3783 | The frequency of hours is 0.000277778 Hz. | |
3784 | The representation is integral | |
3785 | The precision is 3600 seconds. | |
3786 | The range is +/- 244984 years. | |
3787 | sizeof(hours) = 4 | |
3788 | ********* duration<double> ********* | |
3789 | The period of duration<double> is 1 seconds. | |
3790 | The frequency of duration<double> is 1 Hz. | |
3791 | The representation is floating point | |
3792 | The precision is the most significant 15 decimal digits. | |
3793 | The range is +/- 5.69666e+300 years. | |
3794 | sizeof(duration<double>) = 8 | |
3795 | success | |
3796 | test_with_xtime | |
3797 | {3,251000} | |
3798 | 3251 milliseconds | |
3799 | {3,251000} | |
3800 | {3,0} | |
3801 | {3,1} | |
3802 | system_clock test | |
3803 | paused 5001000 nanoseconds | |
3804 | system_clock resolution estimate: 0 nanoseconds | |
3805 | monotonic_clock test | |
3806 | paused 5000181 nanoseconds | |
3807 | monotonic_clock resolution estimate: 97 nanoseconds | |
3808 | high_resolution_clock test | |
3809 | paused 5000277 nanoseconds | |
3810 | high_resolution_clock resolution estimate: 96 nanoseconds | |
3811 | mixed clock test | |
3812 | Add 5 milliseconds to a high_resolution_clock::time_point | |
3813 | Subtracting system_clock::time_point from monotonic_clock::time_point doesn't compile | |
3814 | subtract high_resolution_clock::time_point from monotonic_clock::time_point and add that to a system_clock::time_point | |
3815 | subtract two system_clock::time_point's and output that in microseconds: | |
3816 | 5000 microseconds | |
3817 | timeval_demo system clock test | |
3818 | sizeof xtime_clock::time_point = 8 | |
3819 | sizeof xtime_clock::duration = 8 | |
3820 | sizeof xtime_clock::rep = 8 | |
3821 | paused 5001000 nanoseconds | |
3822 | runtime_resolution test | |
3823 | paused 5000205 nanoseconds | |
3824 | C map test | |
3825 | It is now 10:47:13 2008-4-22 | |
3826 | Round-tripping through the C interface truncated the precision by 255445 microseconds | |
3827 | 2160000 | |
3828 | 0 | |
3829 | 3600000 | |
3830 | 0 | |
3831 | 2999998997 * 1/1000000000 seconds | |
3832 | 0 * 1/1000000000 seconds | |
3833 | 15778476000000000 microseconds | |
3834 | paused 5001000 nanoseconds | |
3835 | ********* milliseconds(3) * 2.5 ********* | |
3836 | The period of milliseconds(3) * 2.5 is 0.001 seconds. | |
3837 | The frequency of milliseconds(3) * 2.5 is 1000 Hz. | |
3838 | The representation is floating point | |
3839 | The precision is the most significant 15 decimal digits. | |
3840 | The range is +/- 5.69666e+297 years. | |
3841 | sizeof(milliseconds(3) * 2.5) = 8 | |
3842 | 7.5 | |
3843 | milliseconds ms(3.5) doesn't compile | |
3844 | ||
3845 | Simulated 400MHz clock which has a tick period of 2.5 nanoseconds | |
3846 | delay = 500 nanoseconds which is 200 cycles | |
3847 | paused 201 cycles which is 502 nanoseconds | |
3848 | ||
3849 | Simulated 400MHz clock modeled with nanoseconds | |
3850 | delay = 500 nanoseconds | |
3851 | paused 503 nanoseconds | |
3852 | ||
3853 | Simulated 1500MHz clock which has a tick period of 0.666667 nanoseconds | |
3854 | delay = 500 nanoseconds which is 750 cycles | |
3855 | paused 751 cycles which is 500 nanoseconds | |
3856 | ||
3857 | Simulated 1500MHz clock modeled with nanoseconds | |
3858 | delay = 500 nanoseconds | |
3859 | paused 500 nanoseconds | |
3860 | duration<unsigned>::min().count() = 0 | |
3861 | duration<unsigned>::zero().count() = 0 | |
3862 | duration<unsigned>::max().count() = 4294967295 | |
3863 | duration<int>::min().count() = -2147483647 | |
3864 | duration<int>::zero().count() = 0 | |
3865 | duration<int>::max().count() = 2147483647 | |
3866 | */</font> | |
3867 | ||
3868 | <font color="#c80000">/* | |
3869 | Example disassemblies (to show efficiency). | |
3870 | Disclaimer: I don't pretend to understand the optimizations made. | |
3871 | ||
3872 | Compiled with | |
3873 | g++ -O3 -arch x86_64 -S test2.cpp | |
3874 | ||
3875 | x86 64-bit architecture | |
3876 | ||
3877 | ******************** | |
3878 | ||
3879 | system_clock::duration | |
3880 | time_subtraction(system_clock::time_point x, system_clock::time_point y) | |
3881 | { | |
3882 | return x - y; | |
3883 | } | |
3884 | ||
3885 | pushq %rbp | |
3886 | LCFI25: | |
3887 | subq %rsi, %rdi | |
3888 | movq %rdi, %rax | |
3889 | movq %rsp, %rbp | |
3890 | LCFI26: | |
3891 | leave | |
3892 | ret | |
3893 | ||
3894 | ******************** | |
3895 | ||
3896 | seconds | |
3897 | time_subtract_to_seconds(system_clock::time_point x, system_clock::time_point y) | |
3898 | { | |
3899 | return duration_cast<seconds>(x - y); | |
3900 | } | |
3901 | ||
3902 | subq %rsi, %rdi | |
3903 | movabsq $4835703278458516699, %rdx | |
3904 | pushq %rbp | |
3905 | LCFI25: | |
3906 | movq %rdi, %rax | |
3907 | sarq $63, %rdi | |
3908 | imulq %rdx | |
3909 | movq %rsp, %rbp | |
3910 | LCFI26: | |
3911 | leave | |
3912 | sarq $18, %rdx | |
3913 | subq %rdi, %rdx | |
3914 | movq %rdx, %rax | |
3915 | ret | |
3916 | ||
3917 | ******************** | |
3918 | ||
3919 | nanoseconds | |
3920 | time_subtract_to_nanoseconds(system_clock::time_point x, system_clock::time_point y) | |
3921 | { | |
3922 | return x - y; | |
3923 | } | |
3924 | ||
3925 | pushq %rbp | |
3926 | LCFI25: | |
3927 | subq %rsi, %rdi | |
3928 | imulq $1000, %rdi, %rax | |
3929 | movq %rsp, %rbp | |
3930 | LCFI26: | |
3931 | leave | |
3932 | ret | |
3933 | ||
3934 | ******************** | |
3935 | ||
3936 | system_clock::time_point | |
3937 | time_plus_duration(system_clock::time_point x, system_clock::duration y) | |
3938 | { | |
3939 | return x + y; | |
3940 | } | |
3941 | ||
3942 | pushq %rbp | |
3943 | LCFI37: | |
3944 | movq %rsp, %rbp | |
3945 | LCFI38: | |
3946 | leaq (%rsi,%rdi), %rax | |
3947 | leave | |
3948 | ret | |
3949 | ||
3950 | ******************** | |
3951 | ||
3952 | milliseconds | |
3953 | duration_plus_duration(milliseconds x, milliseconds y) | |
3954 | { | |
3955 | return x + y; | |
3956 | } | |
3957 | ||
3958 | pushq %rbp | |
3959 | LCFI11: | |
3960 | leaq (%rdi,%rsi), %rax | |
3961 | movq %rsp, %rbp | |
3962 | LCFI12: | |
3963 | leave | |
3964 | ret | |
3965 | ||
3966 | ******************** | |
3967 | ||
3968 | nanoseconds | |
3969 | milliseconds_plus_nanoseconds(milliseconds x, nanoseconds y) | |
3970 | { | |
3971 | return x + y; | |
3972 | } | |
3973 | ||
3974 | imulq $1000000, %rdi, %rdi | |
3975 | pushq %rbp | |
3976 | LCFI20: | |
3977 | movq %rsp, %rbp | |
3978 | LCFI21: | |
3979 | leave | |
3980 | leaq (%rdi,%rsi), %rax | |
3981 | ret | |
3982 | ||
3983 | ******************** | |
3984 | ||
3985 | milliseconds | |
3986 | nanoseconds_to_milliseconds(nanoseconds x) | |
3987 | { | |
3988 | return duration_cast<milliseconds>(x); | |
3989 | } | |
3990 | ||
3991 | movq %rdi, %rax | |
3992 | movabsq $4835703278458516699, %rdx | |
3993 | pushq %rbp | |
3994 | LCFI13: | |
3995 | imulq %rdx | |
3996 | sarq $63, %rdi | |
3997 | movq %rsp, %rbp | |
3998 | LCFI14: | |
3999 | leave | |
4000 | sarq $18, %rdx | |
4001 | subq %rdi, %rdx | |
4002 | movq %rdx, %rax | |
4003 | ret | |
4004 | ||
4005 | ******************** | |
4006 | ||
4007 | nanoseconds | |
4008 | milliseconds_to_nanoseconds(milliseconds x) | |
4009 | { | |
4010 | return x; | |
4011 | } | |
4012 | ||
4013 | pushq %rbp | |
4014 | LCFI13: | |
4015 | imulq $1000000, %rdi, %rax | |
4016 | movq %rsp, %rbp | |
4017 | LCFI14: | |
4018 | leave | |
4019 | ret | |
4020 | ||
4021 | ******************** | |
4022 | ||
4023 | hours | |
4024 | increment_hours(hours x) | |
4025 | { | |
4026 | return ++x; | |
4027 | } | |
4028 | ||
4029 | pushq %rbp | |
4030 | LCFI11: | |
4031 | leaq 1(%rdi), %rax | |
4032 | movq %rsp, %rbp | |
4033 | LCFI12: | |
4034 | leave | |
4035 | ret | |
4036 | ||
4037 | */</font> | |
4038 | </pre> | |
4039 | ||
4040 | </body></html> |