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 <iosfwd>
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;
process_timesboost::chrono::process_times85             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>
process_timesboost::chrono::process_times92             explicit process_times(
93                 Rep2 r)
94                 : real(r)
95                 , user(r)
96                 , system(r){}
97 #endif
98             template <typename Rep2>
process_timesboost::chrono::process_times99             explicit process_times(
100                 process_times<Rep2> const& rhs)
101                 : real(rhs.real)
102                 , user(rhs.user)
103                 , system(rhs.system){}
process_timesboost::chrono::process_times104             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
operator repboost::chrono::process_times117             operator rep() const
118             {
119               return real;
120             }
121 #endif
122             template <typename Rep2>
operator ==boost::chrono::process_times123             bool operator==(process_times<Rep2> const& rhs) {
124                 return (real==rhs.real &&
125                         user==rhs.user &&
126                         system==rhs.system);
127             }
128 
operator +=boost::chrono::process_times129             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             }
operator -=boost::chrono::process_times137             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             }
operator *=boost::chrono::process_times145             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             }
operator *=boost::chrono::process_times153             process_times& operator*=(rep const& rhs)
154             {
155                 real*=rhs;
156                 user*=rhs;
157                 system*=rhs;
158                 return *this;
159             }
operator /=boost::chrono::process_times160             process_times& operator/=(process_times const& rhs)
161             {
162                 real/=rhs.real;
163                 user/=rhs.user;
164                 system/=rhs.system;
165                 return *this;
166             }
operator /=boost::chrono::process_times167             process_times& operator/=(rep const& rhs)
168             {
169                 real/=rhs;
170                 user/=rhs;
171                 system/=rhs;
172                 return *this;
173             }
operator <boost::chrono::process_times174             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>
printboost::chrono::process_times185             void print(std::basic_ostream<CharT, Traits>& os) const
186             {
187                 os <<  "{"<< real <<";"<< user <<";"<< system << "}";
188             }
189 
190             template <class CharT, class Traits>
readboost::chrono::process_times191             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
operator ==(const duration<process_times<Rep1>,Period1> & lhs,const duration<process_times<Rep2>,Period2> & rhs)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<Rep1, Period1>, duration<Rep2, Period2>
248         >()(duration<Rep1, Period1>(lhs.count().real), duration<Rep2, Period2>(rhs.count().real));
249   }
250 
251   template <class Rep1, class Period1, class Rep2, class Period2>
252   inline BOOST_CONSTEXPR
253   bool
operator ==(const duration<process_times<Rep1>,Period1> & lhs,const duration<Rep2,Period2> & rhs)254   operator==(const duration<process_times<Rep1>, Period1>& lhs,
255         const duration<Rep2, Period2>& rhs)
256   {
257       return boost::chrono::detail::duration_eq<
258           duration<Rep1, Period1>, duration<Rep2, Period2> >()(duration<Rep1, Period1>(lhs.count().real), rhs);
259   }
260 
261   template <class Rep1, class Period1, class Rep2, class Period2>
262   inline BOOST_CONSTEXPR
263   bool
operator ==(const duration<Rep1,Period1> & lhs,const duration<process_times<Rep2>,Period2> & rhs)264   operator==(const duration<Rep1, Period1>& lhs,
265         const duration<process_times<Rep2>, Period2>& rhs)
266   {
267       return rhs == lhs;
268   }
269 
270 
271   // Duration <
272 
273   template <class Rep1, class Period1, class Rep2, class Period2>
274   inline BOOST_CONSTEXPR
275   bool
operator <(const duration<process_times<Rep1>,Period1> & lhs,const duration<Rep2,Period2> & rhs)276   operator< (const duration<process_times<Rep1>, Period1>& lhs,
277         const duration<Rep2, Period2>& rhs)
278   {
279       return boost::chrono::detail::duration_lt<
280         duration<Rep1, Period1>, duration<Rep2, Period2> >()(duration<Rep1, Period1>(lhs.count().real), rhs);
281   }
282 
283   template <class Rep1, class Period1, class Rep2, class Period2>
284   inline BOOST_CONSTEXPR
285   bool
operator <(const duration<Rep1,Period1> & lhs,const duration<process_times<Rep2>,Period2> & rhs)286   operator< (const duration<Rep1, Period1>& lhs,
287         const duration<process_times<Rep2>, Period2>& rhs)
288   {
289       return boost::chrono::detail::duration_lt<
290         duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, duration<Rep2, Period2>(rhs.count().real));
291   }
292 
293   template <class Rep1, class Period1, class Rep2, class Period2>
294   inline BOOST_CONSTEXPR
295   bool
operator <(const duration<process_times<Rep1>,Period1> & lhs,const duration<process_times<Rep2>,Period2> & rhs)296   operator< (const duration<process_times<Rep1>, Period1>& lhs,
297         const duration<process_times<Rep2>, Period2>& rhs)
298   {
299     return boost::chrono::detail::duration_lt<
300         duration<Rep1, Period1>, duration<Rep2, Period2>
301       >()(duration<Rep1, Period1>(lhs.count().real), duration<Rep2, Period2>(rhs.count().real));
302   }
303 
304 
305   typedef process_times<nanoseconds::rep> process_cpu_clock_times;
306 #if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP
307     class BOOST_CHRONO_DECL process_cpu_clock
308     {
309     public:
310 
311         typedef process_cpu_clock_times times;
312         typedef boost::chrono::duration<times,  nano>                duration;
313         typedef duration::rep                       rep;
314         typedef duration::period                    period;
315         typedef chrono::time_point<process_cpu_clock>  time_point;
316         BOOST_STATIC_CONSTEXPR bool is_steady =           true;
317 
318         static BOOST_CHRONO_INLINE time_point now() BOOST_NOEXCEPT;
319 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
320         static BOOST_CHRONO_INLINE time_point now(system::error_code & ec );
321 #endif
322     };
323 #endif
324 
325     template <class CharT, class Traits, typename Rep>
326     std::basic_ostream<CharT, Traits>&
operator <<(std::basic_ostream<CharT,Traits> & os,process_times<Rep> const & rhs)327     operator<<(std::basic_ostream<CharT, Traits>& os,
328         process_times<Rep> const& rhs)
329     {
330         rhs.print(os);
331         return os;
332     }
333 
334     template <class CharT, class Traits, typename Rep>
335     std::basic_istream<CharT, Traits>&
operator >>(std::basic_istream<CharT,Traits> & is,process_times<Rep> & rhs)336     operator>>(std::basic_istream<CharT, Traits>& is,
337         process_times<Rep>& rhs)
338     {
339         rhs.read(is);
340         return is;
341     }
342 
343     template <typename Rep>
344     struct duration_values<process_times<Rep> >
345     {
346         typedef process_times<Rep> Res;
347     public:
zeroboost::chrono::duration_values348         static Res zero()
349         {
350             return Res();
351         }
BOOST_PREVENT_MACRO_SUBSTITUTIONboost::chrono::duration_values352         static Res max BOOST_PREVENT_MACRO_SUBSTITUTION ()
353         {
354           return Res((std::numeric_limits<Rep>::max)(),
355                       (std::numeric_limits<Rep>::max)(),
356                       (std::numeric_limits<Rep>::max)());
357         }
BOOST_PREVENT_MACRO_SUBSTITUTIONboost::chrono::duration_values358         static Res min BOOST_PREVENT_MACRO_SUBSTITUTION ()
359         {
360           return Res((std::numeric_limits<Rep>::min)(),
361                       (std::numeric_limits<Rep>::min)(),
362                       (std::numeric_limits<Rep>::min)());
363         }
364     };
365 
366     template<class CharT>
367     struct clock_string<process_real_cpu_clock, CharT>
368     {
nameboost::chrono::clock_string369       static std::basic_string<CharT> name()
370       {
371         static const CharT
372             u[] =
373                 { 'p', 'r', 'o', 'c', 'e', 's', 's', '_', 'r', 'e', 'a', 'l', '_', 'c', 'l', 'o', 'c', 'k' };
374         static const std::basic_string<CharT> str(u, u + sizeof(u)
375             / sizeof(u[0]));
376         return str;
377       }
sinceboost::chrono::clock_string378       static std::basic_string<CharT> since()
379       {
380         const CharT
381             u[] =
382                 { ' ', 's', 'i', 'n', 'c', 'e', ' ', 'p', 'r', 'o', 'c', 'e', 's', 's', ' ', 's', 't', 'a', 'r', 't', '-', 'u', 'p' };
383         const std::basic_string<CharT> str(u, u + sizeof(u) / sizeof(u[0]));
384         return str;
385       }
386     };
387 
388 #if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP
389     template<class CharT>
390     struct clock_string<process_user_cpu_clock, CharT>
391     {
nameboost::chrono::clock_string392       static std::basic_string<CharT> name()
393       {
394         static const CharT
395             u[] =
396                 { 'p', 'r', 'o', 'c', 'e', 's', 's', '_', 'u', 's', 'e', 'r', '_', 'c', 'l', 'o', 'c', 'k' };
397         static const std::basic_string<CharT> str(u, u + sizeof(u)
398             / sizeof(u[0]));
399         return str;
400       }
sinceboost::chrono::clock_string401       static std::basic_string<CharT> since()
402       {
403         const CharT
404             u[] =
405                 { ' ', 's', 'i', 'n', 'c', 'e', ' ', 'p', 'r', 'o', 'c', 'e', 's', 's', ' ', 's', 't', 'a', 'r', 't', '-', 'u', 'p' };
406         const std::basic_string<CharT> str(u, u + sizeof(u) / sizeof(u[0]));
407         return str;
408       }
409     };
410 
411     template<class CharT>
412     struct clock_string<process_system_cpu_clock, CharT>
413     {
nameboost::chrono::clock_string414       static std::basic_string<CharT> name()
415       {
416         static const CharT
417             u[] =
418                 { 'p', 'r', 'o', 'c', 'e', 's', 's', '_', 's', 'y', 's', 't', 'e', 'm', '_', 'c', 'l', 'o', 'c', 'k' };
419         static const std::basic_string<CharT> str(u, u + sizeof(u)
420             / sizeof(u[0]));
421         return str;
422       }
sinceboost::chrono::clock_string423       static std::basic_string<CharT> since()
424       {
425         const CharT
426             u[] =
427                 { ' ', 's', 'i', 'n', 'c', 'e', ' ', 'p', 'r', 'o', 'c', 'e', 's', 's', ' ', 's', 't', 'a', 'r', 't', '-', 'u', 'p' };
428         const std::basic_string<CharT> str(u, u + sizeof(u) / sizeof(u[0]));
429         return str;
430       }
431     };
432 
433     template<class CharT>
434     struct clock_string<process_cpu_clock, CharT>
435     {
nameboost::chrono::clock_string436       static std::basic_string<CharT> name()
437       {
438         static const CharT u[] =
439         { 'p', 'r', 'o', 'c', 'e', 's', 's', '_', 'c', 'l', 'o', 'c', 'k' };
440         static const std::basic_string<CharT> str(u, u + sizeof(u)
441             / sizeof(u[0]));
442         return str;
443       }
sinceboost::chrono::clock_string444       static std::basic_string<CharT> since()
445       {
446         const CharT
447             u[] =
448                 { ' ', 's', 'i', 'n', 'c', 'e', ' ', 'p', 'r', 'o', 'c', 'e', 's', 's', ' ', 's', 't', 'a', 'r', 't', '-', 'u', 'p' };
449         const std::basic_string<CharT> str(u, u + sizeof(u) / sizeof(u[0]));
450         return str;
451       }
452     };
453 #endif
454 
455 } // namespace chrono
456 } // namespace boost
457 
458 namespace std {
459 
460     template <typename Rep>
461     struct numeric_limits<boost::chrono::process_times<Rep> >
462     {
463         typedef boost::chrono::process_times<Rep> Res;
464 
465         public:
466         static const bool is_specialized = true;
BOOST_PREVENT_MACRO_SUBSTITUTIONstd::numeric_limits467         static Res min BOOST_PREVENT_MACRO_SUBSTITUTION ()
468         {
469           return Res((std::numeric_limits<Rep>::min)(),
470                       (std::numeric_limits<Rep>::min)(),
471                       (std::numeric_limits<Rep>::min)());
472         }
BOOST_PREVENT_MACRO_SUBSTITUTIONstd::numeric_limits473         static Res max BOOST_PREVENT_MACRO_SUBSTITUTION ()
474         {
475           return Res((std::numeric_limits<Rep>::max)(),
476                       (std::numeric_limits<Rep>::max)(),
477                       (std::numeric_limits<Rep>::max)());
478         }
loweststd::numeric_limits479         static Res lowest() BOOST_NOEXCEPT_OR_NOTHROW
480         {
481             return (min)();
482         }
483         static const int digits = std::numeric_limits<Rep>::digits+
484                         std::numeric_limits<Rep>::digits+
485                         std::numeric_limits<Rep>::digits;
486         static const int digits10 = std::numeric_limits<Rep>::digits10+
487                         std::numeric_limits<Rep>::digits10+
488                         std::numeric_limits<Rep>::digits10;
489         static const bool is_signed = Rep::is_signed;
490         static const bool is_integer = Rep::is_integer;
491         static const bool is_exact = Rep::is_exact;
492         static const int radix = 0;
493         //~ static Res epsilon() throw() { return 0; }
494         //~ static Res round_error() throw() { return 0; }
495         //~ static const int min_exponent = 0;
496         //~ static const int min_exponent10 = 0;
497         //~ static const int max_exponent = 0;
498         //~ static const int max_exponent10 = 0;
499         //~ static const bool has_infinity = false;
500         //~ static const bool has_quiet_NaN = false;
501         //~ static const bool has_signaling_NaN = false;
502         //~ static const float_denorm_style has_denorm = denorm_absent;
503         //~ static const bool has_denorm_loss = false;
504         //~ static Res infinity() throw() { return 0; }
505         //~ static Res quiet_NaN() throw() { return 0; }
506         //~ static Res signaling_NaN() throw() { return 0; }
507         //~ static Res denorm_min() throw() { return 0; }
508         //~ static const bool is_iec559 = false;
509         //~ static const bool is_bounded = true;
510         //~ static const bool is_modulo = false;
511         //~ static const bool traps = false;
512         //~ static const bool tinyness_before = false;
513         //~ static const float_round_style round_style = round_toward_zero;
514 
515     };
516 }
517 
518 #ifndef BOOST_CHRONO_HEADER_ONLY
519 #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
520 #else
521 #include <boost/chrono/detail/inlined/process_cpu_clocks.hpp>
522 #endif
523 #endif
524 
525 #endif  // BOOST_CHRONO_PROCESS_CPU_CLOCKS_HPP
526