1 //  boost/chrono/system_clocks.hpp  --------------------------------------------------------------//
2 
3 //  Copyright 2008 Howard Hinnant
4 //  Copyright 2008 Beman Dawes
5 //  Copyright 2009-2011 Vicente J. Botet Escriba
6 
7 //  Distributed under the Boost Software License, Version 1.0.
8 //  See http://www.boost.org/LICENSE_1_0.txt
9 
10 /*
11 
12 This code was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
13 Many thanks to Howard for making his code available under the Boost license.
14 The original code was modified to conform to Boost conventions and to section
15 20.9 Time utilities [time] of the C++ committee's working paper N2798.
16 See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
17 
18 time2_demo contained this comment:
19 
20     Much thanks to Andrei Alexandrescu,
21                    Walter Brown,
22                    Peter Dimov,
23                    Jeff Garland,
24                    Terry Golubiewski,
25                    Daniel Krugler,
26                    Anthony Williams.
27 */
28 
29 /*
30 
31 TODO:
32 
33   * Fully implement error handling, with test cases.
34   * Consider issues raised by Michael Marcin:
35 
36     > In the past I've seen QueryPerformanceCounter give incorrect results,
37     > especially with SpeedStep processors on laptops. This was many years ago and
38     > might have been fixed by service packs and drivers.
39     >
40     > Typically you check the results of QPC against GetTickCount to see if the
41     > results are reasonable.
42     > http://support.microsoft.com/kb/274323
43     >
44     > I've also heard of problems with QueryPerformanceCounter in multi-processor
45     > systems.
46     >
47     > I know some people SetThreadAffinityMask to 1 for the current thread call
48     > their QueryPerformance* functions then restore SetThreadAffinityMask. This
49     > seems horrible to me because it forces your program to jump to another
50     > physical processor if it isn't already on cpu0 but they claim it worked well
51     > in practice because they called the timing functions infrequently.
52     >
53     > In the past I have chosen to use timeGetTime with timeBeginPeriod(1) for
54     > high resolution timers to avoid these issues.
55 
56 */
57 
58 #ifndef BOOST_CHRONO_SYSTEM_CLOCKS_HPP
59 #define BOOST_CHRONO_SYSTEM_CLOCKS_HPP
60 
61 #include <boost/chrono/config.hpp>
62 #include <boost/chrono/duration.hpp>
63 #include <boost/chrono/time_point.hpp>
64 #include <boost/chrono/detail/system.hpp>
65 #include <boost/chrono/clock_string.hpp>
66 
67 #include <ctime>
68 
69 # if defined( BOOST_CHRONO_POSIX_API )
70 #   if ! defined(CLOCK_REALTIME) && ! defined (__hpux__)
71 #     error <time.h> does not supply CLOCK_REALTIME
72 #   endif
73 # endif
74 
75 #ifdef BOOST_CHRONO_WINDOWS_API
76 // The system_clock tick is 100 nanoseconds
77 # define BOOST_SYSTEM_CLOCK_DURATION boost::chrono::duration<boost::int_least64_t, ratio<BOOST_RATIO_INTMAX_C(1), BOOST_RATIO_INTMAX_C(10000000)> >
78 #else
79 # define BOOST_SYSTEM_CLOCK_DURATION boost::chrono::nanoseconds
80 #endif
81 
82 // this must occur after all of the includes and before any code appears:
83 #ifndef BOOST_CHRONO_HEADER_ONLY
84 #include <boost/config/abi_prefix.hpp> // must be the last #include
85 #endif
86 
87 
88 //----------------------------------------------------------------------------//
89 //                                                                            //
90 //                        20.9 Time utilities [time]                          //
91 //                                 synopsis                                   //
92 //                                                                            //
93 //----------------------------------------------------------------------------//
94 
95 namespace boost {
96 namespace chrono {
97 
98   // Clocks
99   class BOOST_CHRONO_DECL system_clock;
100 #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
101   class BOOST_CHRONO_DECL steady_clock;
102 #endif
103 
104 #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
105   typedef steady_clock high_resolution_clock;  // as permitted by [time.clock.hires]
106 #else
107   typedef system_clock high_resolution_clock;  // as permitted by [time.clock.hires]
108 #endif
109 
110 //----------------------------------------------------------------------------//
111 //                                                                            //
112 //      20.9.5 Clocks [time.clock]                                            //
113 //                                                                            //
114 //----------------------------------------------------------------------------//
115 
116 // If you're porting, clocks are the system-specific (non-portable) part.
117 // You'll need to know how to get the current time and implement that under now().
118 // You'll need to know what units (tick period) and representation makes the most
119 // sense for your clock and set those accordingly.
120 // If you know how to map this clock to time_t (perhaps your clock is std::time, which
121 // makes that trivial), then you can fill out system_clock's to_time_t() and from_time_t().
122 
123 //----------------------------------------------------------------------------//
124 //      20.9.5.1 Class system_clock [time.clock.system]                       //
125 //----------------------------------------------------------------------------//
126 
127   class BOOST_CHRONO_DECL system_clock
128   {
129   public:
130       typedef BOOST_SYSTEM_CLOCK_DURATION          duration;
131       typedef duration::rep                        rep;
132       typedef duration::period                     period;
133       typedef chrono::time_point<system_clock>     time_point;
134       BOOST_STATIC_CONSTEXPR bool is_steady =             false;
135 
136       static BOOST_CHRONO_INLINE time_point  now() BOOST_NOEXCEPT;
137 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
138       static BOOST_CHRONO_INLINE time_point  now(system::error_code & ec);
139 #endif
140 
141       static BOOST_CHRONO_INLINE std::time_t to_time_t(const time_point& t) BOOST_NOEXCEPT;
142       static BOOST_CHRONO_INLINE time_point  from_time_t(std::time_t t) BOOST_NOEXCEPT;
143   };
144 
145 //----------------------------------------------------------------------------//
146 //      20.9.5.2 Class steady_clock [time.clock.steady]                 //
147 //----------------------------------------------------------------------------//
148 
149 // As permitted  by [time.clock.steady]
150 // The class steady_clock is conditionally supported.
151 
152 #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
153   class BOOST_CHRONO_DECL steady_clock
154   {
155   public:
156       typedef nanoseconds                          duration;
157       typedef duration::rep                        rep;
158       typedef duration::period                     period;
159       typedef chrono::time_point<steady_clock>  time_point;
160       BOOST_STATIC_CONSTEXPR bool is_steady =             true;
161 
162       static BOOST_CHRONO_INLINE time_point  now() BOOST_NOEXCEPT;
163 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
164       static BOOST_CHRONO_INLINE time_point  now(system::error_code & ec);
165 #endif
166   };
167 #endif
168 //----------------------------------------------------------------------------//
169 //      20.9.5.3 Class high_resolution_clock [time.clock.hires]               //
170 //----------------------------------------------------------------------------//
171 
172 //  As permitted, steady_clock or system_clock is a typedef for high_resolution_clock.
173 //  See synopsis.
174 
175 
176   template<class CharT>
177   struct clock_string<system_clock, CharT>
178   {
nameboost::chrono::clock_string179     static std::basic_string<CharT> name()
180     {
181       static const CharT u[] =
182       { 's', 'y', 's', 't', 'e', 'm', '_', 'c', 'l', 'o', 'c', 'k' };
183       static const std::basic_string<CharT> str(u, u + sizeof(u)
184           / sizeof(u[0]));
185       return str;
186     }
sinceboost::chrono::clock_string187     static std::basic_string<CharT> since()
188     {
189       static const CharT
190           u[] =
191               { ' ', 's', 'i', 'n', 'c', 'e', ' ', 'J', 'a', 'n', ' ', '1', ',', ' ', '1', '9', '7', '0' };
192       static const std::basic_string<CharT> str(u, u + sizeof(u)
193           / sizeof(u[0]));
194       return str;
195     }
196   };
197 
198 #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
199 
200   template<class CharT>
201   struct clock_string<steady_clock, CharT>
202   {
nameboost::chrono::clock_string203     static std::basic_string<CharT> name()
204     {
205       static const CharT
206           u[] =
207               { 's', 't', 'e', 'a', 'd', 'y', '_', 'c', 'l', 'o', 'c', 'k' };
208       static const std::basic_string<CharT> str(u, u + sizeof(u)
209           / sizeof(u[0]));
210       return str;
211     }
sinceboost::chrono::clock_string212     static std::basic_string<CharT> since()
213     {
214       const CharT u[] =
215       { ' ', 's', 'i', 'n', 'c', 'e', ' ', 'b', 'o', 'o', 't' };
216       const std::basic_string<CharT> str(u, u + sizeof(u) / sizeof(u[0]));
217       return str;
218     }
219   };
220 
221 #endif
222 
223 } // namespace chrono
224 } // namespace boost
225 
226 #ifndef BOOST_CHRONO_HEADER_ONLY
227 // the suffix header occurs after all of our code:
228 #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
229 #else
230 #include <boost/chrono/detail/inlined/chrono.hpp>
231 #endif
232 
233 #endif // BOOST_CHRONO_SYSTEM_CLOCKS_HPP
234