1 | // boost/chrono/process_cpu_clocks.hpp -----------------------------------------------------------// |
2 | |
3 | // Copyright 2009-2011 Vicente J. Botet Escriba |
4 | // Copyright (c) Microsoft Corporation 2014 |
5 | |
6 | // Distributed under the Boost Software License, Version 1.0. |
7 | // See http://www.boost.org/LICENSE_1_0.txt |
8 | |
9 | // See http://www.boost.org/libs/system for documentation. |
10 | |
11 | #ifndef BOOST_CHRONO_PROCESS_CPU_CLOCKS_HPP |
12 | #define BOOST_CHRONO_PROCESS_CPU_CLOCKS_HPP |
13 | |
14 | #include <boost/chrono/config.hpp> |
15 | |
16 | |
17 | #if defined(BOOST_CHRONO_HAS_PROCESS_CLOCKS) |
18 | |
19 | #include <boost/chrono/duration.hpp> |
20 | #include <boost/chrono/time_point.hpp> |
21 | #include <boost/operators.hpp> |
22 | #include <boost/chrono/detail/system.hpp> |
23 | #include <iostream> |
24 | #include <boost/type_traits/common_type.hpp> |
25 | #include <boost/chrono/clock_string.hpp> |
26 | |
27 | #ifndef BOOST_CHRONO_HEADER_ONLY |
28 | #include <boost/config/abi_prefix.hpp> // must be the last #include |
29 | #endif |
30 | |
31 | namespace boost { namespace chrono { |
32 | |
33 | class BOOST_CHRONO_DECL process_real_cpu_clock { |
34 | public: |
35 | typedef nanoseconds duration; |
36 | typedef duration::rep rep; |
37 | typedef duration::period period; |
38 | typedef chrono::time_point<process_real_cpu_clock> time_point; |
39 | BOOST_STATIC_CONSTEXPR bool is_steady = true; |
40 | |
41 | static BOOST_CHRONO_INLINE time_point now() BOOST_NOEXCEPT; |
42 | #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING |
43 | static BOOST_CHRONO_INLINE time_point now(system::error_code & ec ); |
44 | #endif |
45 | }; |
46 | |
47 | #if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP |
48 | class BOOST_CHRONO_DECL process_user_cpu_clock { |
49 | public: |
50 | typedef nanoseconds duration; |
51 | typedef duration::rep rep; |
52 | typedef duration::period period; |
53 | typedef chrono::time_point<process_user_cpu_clock> time_point; |
54 | BOOST_STATIC_CONSTEXPR bool is_steady = true; |
55 | |
56 | static BOOST_CHRONO_INLINE time_point now() BOOST_NOEXCEPT; |
57 | #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING |
58 | static BOOST_CHRONO_INLINE time_point now(system::error_code & ec ); |
59 | #endif |
60 | }; |
61 | |
62 | class BOOST_CHRONO_DECL process_system_cpu_clock { |
63 | public: |
64 | typedef nanoseconds duration; |
65 | typedef duration::rep rep; |
66 | typedef duration::period period; |
67 | typedef chrono::time_point<process_system_cpu_clock> time_point; |
68 | BOOST_STATIC_CONSTEXPR bool is_steady = true; |
69 | |
70 | static BOOST_CHRONO_INLINE time_point now() BOOST_NOEXCEPT; |
71 | #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING |
72 | static BOOST_CHRONO_INLINE time_point now(system::error_code & ec ); |
73 | #endif |
74 | }; |
75 | #endif |
76 | |
77 | template <typename Rep> |
78 | struct process_times |
79 | : arithmetic<process_times<Rep>, |
80 | multiplicative<process_times<Rep>, Rep, |
81 | less_than_comparable<process_times<Rep> > > > |
82 | { |
83 | //typedef process_real_cpu_clock::rep rep; |
84 | typedef Rep rep; |
85 | process_times() |
86 | : real(0) |
87 | , user(0) |
88 | , system(0){} |
89 | |
90 | #if ! defined BOOST_CHRONO_DONT_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 |
91 | template <typename Rep2> |
92 | explicit process_times( |
93 | Rep2 r) |
94 | : real(r) |
95 | , user(r) |
96 | , system(r){} |
97 | #endif |
98 | template <typename Rep2> |
99 | explicit process_times( |
100 | process_times<Rep2> const& rhs) |
101 | : real(rhs.real) |
102 | , user(rhs.user) |
103 | , system(rhs.system){} |
104 | process_times( |
105 | rep r, |
106 | rep u, |
107 | rep s) |
108 | : real(r) |
109 | , user(u) |
110 | , system(s){} |
111 | |
112 | rep real; // real (i.e wall clock) time |
113 | rep user; // user cpu time |
114 | rep system; // system cpu time |
115 | |
116 | #if ! defined BOOST_CHRONO_DONT_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 |
117 | operator rep() const |
118 | { |
119 | return real; |
120 | } |
121 | #endif |
122 | template <typename Rep2> |
123 | bool operator==(process_times<Rep2> const& rhs) { |
124 | return (real==rhs.real && |
125 | user==rhs.user && |
126 | system==rhs.system); |
127 | } |
128 | |
129 | process_times& operator+=( |
130 | process_times const& rhs) |
131 | { |
132 | real+=rhs.real; |
133 | user+=rhs.user; |
134 | system+=rhs.system; |
135 | return *this; |
136 | } |
137 | process_times& operator-=( |
138 | process_times const& rhs) |
139 | { |
140 | real-=rhs.real; |
141 | user-=rhs.user; |
142 | system-=rhs.system; |
143 | return *this; |
144 | } |
145 | process_times& operator*=( |
146 | process_times const& rhs) |
147 | { |
148 | real*=rhs.real; |
149 | user*=rhs.user; |
150 | system*=rhs.system; |
151 | return *this; |
152 | } |
153 | process_times& operator*=(rep const& rhs) |
154 | { |
155 | real*=rhs; |
156 | user*=rhs; |
157 | system*=rhs; |
158 | return *this; |
159 | } |
160 | process_times& operator/=(process_times const& rhs) |
161 | { |
162 | real/=rhs.real; |
163 | user/=rhs.user; |
164 | system/=rhs.system; |
165 | return *this; |
166 | } |
167 | process_times& operator/=(rep const& rhs) |
168 | { |
169 | real/=rhs; |
170 | user/=rhs; |
171 | system/=rhs; |
172 | return *this; |
173 | } |
174 | bool operator<(process_times const & rhs) const |
175 | { |
176 | if (real < rhs.real) return true; |
177 | if (real > rhs.real) return false; |
178 | if (user < rhs.user) return true; |
179 | if (user > rhs.user) return false; |
180 | if (system < rhs.system) return true; |
181 | else return false; |
182 | } |
183 | |
184 | template <class CharT, class Traits> |
185 | void print(std::basic_ostream<CharT, Traits>& os) const |
186 | { |
187 | os << "{" << real <<";" << user <<";" << system << "}" ; |
188 | } |
189 | |
190 | template <class CharT, class Traits> |
191 | void read(std::basic_istream<CharT, Traits>& is) |
192 | { |
193 | typedef std::istreambuf_iterator<CharT, Traits> in_iterator; |
194 | in_iterator i(is); |
195 | in_iterator e; |
196 | if (i == e || *i != '{') // mandatory '{' |
197 | { |
198 | is.setstate(is.failbit | is.eofbit); |
199 | return; |
200 | } |
201 | CharT x,y,z; |
202 | is >> real >> x >> user >> y >> system >> z; |
203 | if (!is.good() || (x != ';')|| (y != ';')|| (z != '}')) |
204 | { |
205 | is.setstate(is.failbit); |
206 | } |
207 | } |
208 | }; |
209 | } |
210 | template <class Rep1, class Rep2> |
211 | struct common_type< |
212 | chrono::process_times<Rep1>, |
213 | chrono::process_times<Rep2> |
214 | > |
215 | { |
216 | typedef chrono::process_times<typename common_type<Rep1, Rep2>::type> type; |
217 | }; |
218 | |
219 | template <class Rep1, class Rep2> |
220 | struct common_type< |
221 | chrono::process_times<Rep1>, |
222 | Rep2 |
223 | > |
224 | { |
225 | typedef chrono::process_times<typename common_type<Rep1, Rep2>::type> type; |
226 | }; |
227 | |
228 | template <class Rep1, class Rep2> |
229 | struct common_type< |
230 | Rep1, |
231 | chrono::process_times<Rep2> |
232 | > |
233 | { |
234 | typedef chrono::process_times<typename common_type<Rep1, Rep2>::type> type; |
235 | }; |
236 | |
237 | |
238 | namespace chrono |
239 | { |
240 | template <class Rep1, class Period1, class Rep2, class Period2> |
241 | inline BOOST_CONSTEXPR |
242 | bool |
243 | operator==(const duration<process_times<Rep1>, Period1>& lhs, |
244 | const duration<process_times<Rep2>, Period2>& rhs) |
245 | { |
246 | return boost::chrono::detail::duration_eq< |
247 | duration<process_times<Rep1>, Period1>, duration<process_times<Rep2>, Period2> >()(lhs, rhs); |
248 | } |
249 | |
250 | template <class Rep1, class Period1, class Rep2, class Period2> |
251 | inline BOOST_CONSTEXPR |
252 | bool |
253 | operator==(const duration<process_times<Rep1>, Period1>& lhs, |
254 | const duration<Rep2, Period2>& rhs) |
255 | { |
256 | return boost::chrono::detail::duration_eq< |
257 | duration<Rep1, Period1>, duration<Rep2, Period2> >()(duration<Rep1, Period1>(lhs.count().real), rhs); |
258 | } |
259 | |
260 | template <class Rep1, class Period1, class Rep2, class Period2> |
261 | inline BOOST_CONSTEXPR |
262 | bool |
263 | operator==(const duration<Rep1, Period1>& lhs, |
264 | const duration<process_times<Rep2>, Period2>& rhs) |
265 | { |
266 | return rhs == lhs; |
267 | } |
268 | |
269 | |
270 | // Duration < |
271 | |
272 | template <class Rep1, class Period1, class Rep2, class Period2> |
273 | inline BOOST_CONSTEXPR |
274 | bool |
275 | operator< (const duration<process_times<Rep1>, Period1>& lhs, |
276 | const duration<Rep2, Period2>& rhs) |
277 | { |
278 | return boost::chrono::detail::duration_lt< |
279 | duration<Rep1, Period1>, duration<Rep2, Period2> >()(duration<Rep1, Period1>(lhs.count().real), rhs); |
280 | } |
281 | |
282 | template <class Rep1, class Period1, class Rep2, class Period2> |
283 | inline BOOST_CONSTEXPR |
284 | bool |
285 | operator< (const duration<Rep1, Period1>& lhs, |
286 | const duration<process_times<Rep2>, Period2>& rhs) |
287 | { |
288 | return rhs < lhs; |
289 | } |
290 | |
291 | template <class Rep1, class Period1, class Rep2, class Period2> |
292 | inline BOOST_CONSTEXPR |
293 | bool |
294 | operator< (const duration<process_times<Rep1>, Period1>& lhs, |
295 | const duration<process_times<Rep2>, Period2>& rhs) |
296 | { |
297 | return boost::chrono::detail::duration_lt< |
298 | duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs); |
299 | } |
300 | |
301 | |
302 | typedef process_times<nanoseconds::rep> process_cpu_clock_times; |
303 | #if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP |
304 | class BOOST_CHRONO_DECL process_cpu_clock |
305 | { |
306 | public: |
307 | |
308 | typedef process_cpu_clock_times times; |
309 | typedef boost::chrono::duration<times, nano> duration; |
310 | typedef duration::rep rep; |
311 | typedef duration::period period; |
312 | typedef chrono::time_point<process_cpu_clock> time_point; |
313 | BOOST_STATIC_CONSTEXPR bool is_steady = true; |
314 | |
315 | static BOOST_CHRONO_INLINE time_point now() BOOST_NOEXCEPT; |
316 | #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING |
317 | static BOOST_CHRONO_INLINE time_point now(system::error_code & ec ); |
318 | #endif |
319 | }; |
320 | #endif |
321 | |
322 | template <class CharT, class Traits, typename Rep> |
323 | std::basic_ostream<CharT, Traits>& |
324 | operator<<(std::basic_ostream<CharT, Traits>& os, |
325 | process_times<Rep> const& rhs) |
326 | { |
327 | rhs.print(os); |
328 | return os; |
329 | } |
330 | |
331 | template <class CharT, class Traits, typename Rep> |
332 | std::basic_istream<CharT, Traits>& |
333 | operator>>(std::basic_istream<CharT, Traits>& is, |
334 | process_times<Rep>& rhs) |
335 | { |
336 | rhs.read(is); |
337 | return is; |
338 | } |
339 | |
340 | template <typename Rep> |
341 | struct duration_values<process_times<Rep> > |
342 | { |
343 | typedef process_times<Rep> Res; |
344 | public: |
345 | static Res zero() |
346 | { |
347 | return Res(); |
348 | } |
349 | static Res max BOOST_PREVENT_MACRO_SUBSTITUTION () |
350 | { |
351 | return Res((std::numeric_limits<Rep>::max)(), |
352 | (std::numeric_limits<Rep>::max)(), |
353 | (std::numeric_limits<Rep>::max)()); |
354 | } |
355 | static Res min BOOST_PREVENT_MACRO_SUBSTITUTION () |
356 | { |
357 | return Res((std::numeric_limits<Rep>::min)(), |
358 | (std::numeric_limits<Rep>::min)(), |
359 | (std::numeric_limits<Rep>::min)()); |
360 | } |
361 | }; |
362 | |
363 | template<class CharT> |
364 | struct clock_string<process_real_cpu_clock, CharT> |
365 | { |
366 | static std::basic_string<CharT> name() |
367 | { |
368 | static const CharT |
369 | u[] = |
370 | { 'p', 'r', 'o', 'c', 'e', 's', 's', '_', 'r', 'e', 'a', 'l', '_', 'c', 'l', 'o', 'c', 'k' }; |
371 | static const std::basic_string<CharT> str(u, u + sizeof(u) |
372 | / sizeof(u[0])); |
373 | return str; |
374 | } |
375 | static std::basic_string<CharT> since() |
376 | { |
377 | const CharT |
378 | u[] = |
379 | { ' ', 's', 'i', 'n', 'c', 'e', ' ', 'p', 'r', 'o', 'c', 'e', 's', 's', ' ', 's', 't', 'a', 'r', 't', '-', 'u', 'p' }; |
380 | const std::basic_string<CharT> str(u, u + sizeof(u) / sizeof(u[0])); |
381 | return str; |
382 | } |
383 | }; |
384 | |
385 | #if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP |
386 | template<class CharT> |
387 | struct clock_string<process_user_cpu_clock, CharT> |
388 | { |
389 | static std::basic_string<CharT> name() |
390 | { |
391 | static const CharT |
392 | u[] = |
393 | { 'p', 'r', 'o', 'c', 'e', 's', 's', '_', 'u', 's', 'e', 'r', '_', 'c', 'l', 'o', 'c', 'k' }; |
394 | static const std::basic_string<CharT> str(u, u + sizeof(u) |
395 | / sizeof(u[0])); |
396 | return str; |
397 | } |
398 | static std::basic_string<CharT> since() |
399 | { |
400 | const CharT |
401 | u[] = |
402 | { ' ', 's', 'i', 'n', 'c', 'e', ' ', 'p', 'r', 'o', 'c', 'e', 's', 's', ' ', 's', 't', 'a', 'r', 't', '-', 'u', 'p' }; |
403 | const std::basic_string<CharT> str(u, u + sizeof(u) / sizeof(u[0])); |
404 | return str; |
405 | } |
406 | }; |
407 | |
408 | template<class CharT> |
409 | struct clock_string<process_system_cpu_clock, CharT> |
410 | { |
411 | static std::basic_string<CharT> name() |
412 | { |
413 | static const CharT |
414 | u[] = |
415 | { 'p', 'r', 'o', 'c', 'e', 's', 's', '_', 's', 'y', 's', 't', 't', 'e', 'm', '_', 'c', 'l', 'o', 'c', 'k' }; |
416 | static const std::basic_string<CharT> str(u, u + sizeof(u) |
417 | / sizeof(u[0])); |
418 | return str; |
419 | } |
420 | static std::basic_string<CharT> since() |
421 | { |
422 | const CharT |
423 | u[] = |
424 | { ' ', 's', 'i', 'n', 'c', 'e', ' ', 'p', 'r', 'o', 'c', 'e', 's', 's', ' ', 's', 't', 'a', 'r', 't', '-', 'u', 'p' }; |
425 | const std::basic_string<CharT> str(u, u + sizeof(u) / sizeof(u[0])); |
426 | return str; |
427 | } |
428 | }; |
429 | |
430 | template<class CharT> |
431 | struct clock_string<process_cpu_clock, CharT> |
432 | { |
433 | static std::basic_string<CharT> name() |
434 | { |
435 | static const CharT u[] = |
436 | { 'p', 'r', 'o', 'c', 'e', 's', 's', '_', 'c', 'l', 'o', 'c', 'k' }; |
437 | static const std::basic_string<CharT> str(u, u + sizeof(u) |
438 | / sizeof(u[0])); |
439 | return str; |
440 | } |
441 | static std::basic_string<CharT> since() |
442 | { |
443 | const CharT |
444 | u[] = |
445 | { ' ', 's', 'i', 'n', 'c', 'e', ' ', 'p', 'r', 'o', 'c', 'e', 's', 's', ' ', 's', 't', 'a', 'r', 't', '-', 'u', 'p' }; |
446 | const std::basic_string<CharT> str(u, u + sizeof(u) / sizeof(u[0])); |
447 | return str; |
448 | } |
449 | }; |
450 | #endif |
451 | |
452 | } // namespace chrono |
453 | } // namespace boost |
454 | |
455 | namespace std { |
456 | |
457 | template <typename Rep> |
458 | struct numeric_limits<boost::chrono::process_times<Rep> > |
459 | { |
460 | typedef boost::chrono::process_times<Rep> Res; |
461 | |
462 | public: |
463 | static const bool is_specialized = true; |
464 | static Res min BOOST_PREVENT_MACRO_SUBSTITUTION () |
465 | { |
466 | return Res((std::numeric_limits<Rep>::min)(), |
467 | (std::numeric_limits<Rep>::min)(), |
468 | (std::numeric_limits<Rep>::min)()); |
469 | } |
470 | static Res max BOOST_PREVENT_MACRO_SUBSTITUTION () |
471 | { |
472 | return Res((std::numeric_limits<Rep>::max)(), |
473 | (std::numeric_limits<Rep>::max)(), |
474 | (std::numeric_limits<Rep>::max)()); |
475 | } |
476 | static Res lowest() throw() |
477 | { |
478 | return (min)(); |
479 | } |
480 | static const int digits = std::numeric_limits<Rep>::digits+ |
481 | std::numeric_limits<Rep>::digits+ |
482 | std::numeric_limits<Rep>::digits; |
483 | static const int digits10 = std::numeric_limits<Rep>::digits10+ |
484 | std::numeric_limits<Rep>::digits10+ |
485 | std::numeric_limits<Rep>::digits10; |
486 | static const bool is_signed = Rep::is_signed; |
487 | static const bool is_integer = Rep::is_integer; |
488 | static const bool is_exact = Rep::is_exact; |
489 | static const int radix = 0; |
490 | //~ static Res epsilon() throw() { return 0; } |
491 | //~ static Res round_error() throw() { return 0; } |
492 | //~ static const int min_exponent = 0; |
493 | //~ static const int min_exponent10 = 0; |
494 | //~ static const int max_exponent = 0; |
495 | //~ static const int max_exponent10 = 0; |
496 | //~ static const bool has_infinity = false; |
497 | //~ static const bool has_quiet_NaN = false; |
498 | //~ static const bool has_signaling_NaN = false; |
499 | //~ static const float_denorm_style has_denorm = denorm_absent; |
500 | //~ static const bool has_denorm_loss = false; |
501 | //~ static Res infinity() throw() { return 0; } |
502 | //~ static Res quiet_NaN() throw() { return 0; } |
503 | //~ static Res signaling_NaN() throw() { return 0; } |
504 | //~ static Res denorm_min() throw() { return 0; } |
505 | //~ static const bool is_iec559 = false; |
506 | //~ static const bool is_bounded = true; |
507 | //~ static const bool is_modulo = false; |
508 | //~ static const bool traps = false; |
509 | //~ static const bool tinyness_before = false; |
510 | //~ static const float_round_style round_style = round_toward_zero; |
511 | |
512 | }; |
513 | } |
514 | |
515 | #ifndef BOOST_CHRONO_HEADER_ONLY |
516 | #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas |
517 | #else |
518 | #include <boost/chrono/detail/inlined/process_cpu_clocks.hpp> |
519 | #endif |
520 | #endif |
521 | |
522 | #endif // BOOST_CHRONO_PROCESS_CPU_CLOCKS_HPP |
523 | |