]>
Commit | Line | Data |
---|---|---|
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 system_clock; | |
100 | #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY | |
101 | class 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 | { | |
179 | 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 | } | |
187 | 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 | { | |
203 | 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 | } | |
212 | 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 |