Chris@16
|
1 // mac/chrono.cpp --------------------------------------------------------------//
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright Beman Dawes 2008
|
Chris@16
|
4 // Copyright 2009-2010 Vicente J. Botet Escriba
|
Chris@16
|
5
|
Chris@16
|
6 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
7 // See http://www.boost.org/LICENSE_1_0.txt
|
Chris@16
|
8
|
Chris@16
|
9
|
Chris@16
|
10 //----------------------------------------------------------------------------//
|
Chris@16
|
11 // Mac //
|
Chris@16
|
12 //----------------------------------------------------------------------------//
|
Chris@16
|
13
|
Chris@16
|
14 #include <sys/time.h> //for gettimeofday and timeval
|
Chris@16
|
15 #include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
|
Chris@16
|
16
|
Chris@16
|
17 namespace boost
|
Chris@16
|
18 {
|
Chris@16
|
19 namespace chrono
|
Chris@16
|
20 {
|
Chris@16
|
21
|
Chris@16
|
22 // system_clock
|
Chris@16
|
23
|
Chris@16
|
24 // gettimeofday is the most precise "system time" available on this platform.
|
Chris@16
|
25 // It returns the number of microseconds since New Years 1970 in a struct called timeval
|
Chris@16
|
26 // which has a field for seconds and a field for microseconds.
|
Chris@16
|
27 // Fill in the timeval and then convert that to the time_point
|
Chris@16
|
28 system_clock::time_point
|
Chris@16
|
29 system_clock::now() BOOST_NOEXCEPT
|
Chris@16
|
30 {
|
Chris@16
|
31 timeval tv;
|
Chris@16
|
32 gettimeofday(&tv, 0);
|
Chris@16
|
33 return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
|
Chris@16
|
34 }
|
Chris@16
|
35
|
Chris@16
|
36 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
|
Chris@16
|
37 system_clock::time_point
|
Chris@16
|
38 system_clock::now(system::error_code & ec)
|
Chris@16
|
39 {
|
Chris@16
|
40 timeval tv;
|
Chris@16
|
41 gettimeofday(&tv, 0);
|
Chris@16
|
42 if (!BOOST_CHRONO_IS_THROWS(ec))
|
Chris@16
|
43 {
|
Chris@16
|
44 ec.clear();
|
Chris@16
|
45 }
|
Chris@16
|
46 return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
|
Chris@16
|
47 }
|
Chris@16
|
48 #endif
|
Chris@16
|
49 // Take advantage of the fact that on this platform time_t is nothing but
|
Chris@16
|
50 // an integral count of seconds since New Years 1970 (same epoch as timeval).
|
Chris@16
|
51 // Just get the duration out of the time_point and truncate it to seconds.
|
Chris@16
|
52 time_t
|
Chris@16
|
53 system_clock::to_time_t(const time_point& t) BOOST_NOEXCEPT
|
Chris@16
|
54 {
|
Chris@16
|
55 return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
|
Chris@16
|
56 }
|
Chris@16
|
57
|
Chris@16
|
58 // Just turn the time_t into a count of seconds and construct a time_point with it.
|
Chris@16
|
59 system_clock::time_point
|
Chris@16
|
60 system_clock::from_time_t(time_t t) BOOST_NOEXCEPT
|
Chris@16
|
61 {
|
Chris@16
|
62 return system_clock::time_point(seconds(t));
|
Chris@16
|
63 }
|
Chris@16
|
64
|
Chris@16
|
65 namespace chrono_detail
|
Chris@16
|
66 {
|
Chris@16
|
67
|
Chris@16
|
68 // steady_clock
|
Chris@16
|
69
|
Chris@16
|
70 // Note, in this implementation steady_clock and high_resolution_clock
|
Chris@16
|
71 // are the same clock. They are both based on mach_absolute_time().
|
Chris@16
|
72 // mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
|
Chris@16
|
73 // nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom
|
Chris@16
|
74 // are run time constants supplied by the OS. This clock has no relationship
|
Chris@16
|
75 // to the Gregorian calendar. It's main use is as a high resolution timer.
|
Chris@16
|
76
|
Chris@16
|
77 // MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize
|
Chris@16
|
78 // for that case as an optimization.
|
Chris@16
|
79 BOOST_CHRONO_STATIC
|
Chris@16
|
80 steady_clock::rep
|
Chris@16
|
81 steady_simplified()
|
Chris@16
|
82 {
|
Chris@16
|
83 return mach_absolute_time();
|
Chris@16
|
84 }
|
Chris@16
|
85
|
Chris@16
|
86 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
|
Chris@16
|
87 BOOST_CHRONO_STATIC
|
Chris@16
|
88 steady_clock::rep
|
Chris@16
|
89 steady_simplified_ec(system::error_code & ec)
|
Chris@16
|
90 {
|
Chris@16
|
91 if (!BOOST_CHRONO_IS_THROWS(ec))
|
Chris@16
|
92 {
|
Chris@16
|
93 ec.clear();
|
Chris@16
|
94 }
|
Chris@16
|
95 return mach_absolute_time();
|
Chris@16
|
96 }
|
Chris@16
|
97 #endif
|
Chris@16
|
98
|
Chris@16
|
99 BOOST_CHRONO_STATIC
|
Chris@16
|
100 double
|
Chris@16
|
101 compute_steady_factor(kern_return_t& err)
|
Chris@16
|
102 {
|
Chris@16
|
103 mach_timebase_info_data_t MachInfo;
|
Chris@16
|
104 err = mach_timebase_info(&MachInfo);
|
Chris@16
|
105 if ( err != 0 ) {
|
Chris@16
|
106 return 0;
|
Chris@16
|
107 }
|
Chris@16
|
108 return static_cast<double>(MachInfo.numer) / MachInfo.denom;
|
Chris@16
|
109 }
|
Chris@16
|
110
|
Chris@16
|
111 BOOST_CHRONO_STATIC
|
Chris@16
|
112 steady_clock::rep
|
Chris@16
|
113 steady_full()
|
Chris@16
|
114 {
|
Chris@16
|
115 static kern_return_t err;
|
Chris@16
|
116 static const double factor = chrono_detail::compute_steady_factor(err);
|
Chris@16
|
117 if (err != 0)
|
Chris@16
|
118 {
|
Chris@16
|
119 BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
|
Chris@16
|
120 }
|
Chris@16
|
121 return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
|
Chris@16
|
122 }
|
Chris@16
|
123
|
Chris@16
|
124 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
|
Chris@16
|
125 BOOST_CHRONO_STATIC
|
Chris@16
|
126 steady_clock::rep
|
Chris@16
|
127 steady_full_ec(system::error_code & ec)
|
Chris@16
|
128 {
|
Chris@16
|
129 static kern_return_t err;
|
Chris@16
|
130 static const double factor = chrono_detail::compute_steady_factor(err);
|
Chris@16
|
131 if (err != 0)
|
Chris@16
|
132 {
|
Chris@16
|
133 if (BOOST_CHRONO_IS_THROWS(ec))
|
Chris@16
|
134 {
|
Chris@16
|
135 boost::throw_exception(
|
Chris@16
|
136 system::system_error(
|
Chris@16
|
137 err,
|
Chris@16
|
138 BOOST_CHRONO_SYSTEM_CATEGORY,
|
Chris@16
|
139 "chrono::steady_clock" ));
|
Chris@16
|
140 }
|
Chris@16
|
141 else
|
Chris@16
|
142 {
|
Chris@16
|
143 ec.assign( errno, BOOST_CHRONO_SYSTEM_CATEGORY );
|
Chris@16
|
144 return steady_clock::rep();
|
Chris@16
|
145 }
|
Chris@16
|
146 }
|
Chris@16
|
147 if (!BOOST_CHRONO_IS_THROWS(ec))
|
Chris@16
|
148 {
|
Chris@16
|
149 ec.clear();
|
Chris@16
|
150 }
|
Chris@16
|
151 return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
|
Chris@16
|
152 }
|
Chris@16
|
153 #endif
|
Chris@16
|
154
|
Chris@16
|
155 typedef steady_clock::rep (*FP)();
|
Chris@16
|
156 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
|
Chris@16
|
157 typedef steady_clock::rep (*FP_ec)(system::error_code &);
|
Chris@16
|
158 #endif
|
Chris@16
|
159
|
Chris@16
|
160 BOOST_CHRONO_STATIC
|
Chris@16
|
161 FP
|
Chris@16
|
162 init_steady_clock(kern_return_t & err)
|
Chris@16
|
163 {
|
Chris@16
|
164 mach_timebase_info_data_t MachInfo;
|
Chris@16
|
165 err = mach_timebase_info(&MachInfo);
|
Chris@16
|
166 if ( err != 0 )
|
Chris@16
|
167 {
|
Chris@16
|
168 return 0;
|
Chris@16
|
169 }
|
Chris@16
|
170
|
Chris@16
|
171 if (MachInfo.numer == MachInfo.denom)
|
Chris@16
|
172 {
|
Chris@16
|
173 return &chrono_detail::steady_simplified;
|
Chris@16
|
174 }
|
Chris@16
|
175 return &chrono_detail::steady_full;
|
Chris@16
|
176 }
|
Chris@16
|
177
|
Chris@16
|
178 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
|
Chris@16
|
179 BOOST_CHRONO_STATIC
|
Chris@16
|
180 FP_ec
|
Chris@16
|
181 init_steady_clock_ec(kern_return_t & err)
|
Chris@16
|
182 {
|
Chris@16
|
183 mach_timebase_info_data_t MachInfo;
|
Chris@16
|
184 err = mach_timebase_info(&MachInfo);
|
Chris@16
|
185 if ( err != 0 )
|
Chris@16
|
186 {
|
Chris@16
|
187 return 0;
|
Chris@16
|
188 }
|
Chris@16
|
189
|
Chris@16
|
190 if (MachInfo.numer == MachInfo.denom)
|
Chris@16
|
191 {
|
Chris@16
|
192 return &chrono_detail::steady_simplified_ec;
|
Chris@16
|
193 }
|
Chris@16
|
194 return &chrono_detail::steady_full_ec;
|
Chris@16
|
195 }
|
Chris@16
|
196 #endif
|
Chris@16
|
197 }
|
Chris@16
|
198
|
Chris@16
|
199 steady_clock::time_point
|
Chris@16
|
200 steady_clock::now() BOOST_NOEXCEPT
|
Chris@16
|
201 {
|
Chris@16
|
202 static kern_return_t err;
|
Chris@16
|
203 static chrono_detail::FP fp = chrono_detail::init_steady_clock(err);
|
Chris@16
|
204 if ( err != 0 )
|
Chris@16
|
205 {
|
Chris@16
|
206 BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
|
Chris@16
|
207 }
|
Chris@16
|
208 return time_point(duration(fp()));
|
Chris@16
|
209 }
|
Chris@16
|
210
|
Chris@16
|
211 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
|
Chris@16
|
212 steady_clock::time_point
|
Chris@16
|
213 steady_clock::now(system::error_code & ec)
|
Chris@16
|
214 {
|
Chris@16
|
215 static kern_return_t err;
|
Chris@16
|
216 static chrono_detail::FP_ec fp = chrono_detail::init_steady_clock_ec(err);
|
Chris@16
|
217 if ( err != 0 )
|
Chris@16
|
218 {
|
Chris@16
|
219 if (BOOST_CHRONO_IS_THROWS(ec))
|
Chris@16
|
220 {
|
Chris@16
|
221 boost::throw_exception(
|
Chris@16
|
222 system::system_error(
|
Chris@16
|
223 err,
|
Chris@16
|
224 BOOST_CHRONO_SYSTEM_CATEGORY,
|
Chris@16
|
225 "chrono::steady_clock" ));
|
Chris@16
|
226 }
|
Chris@16
|
227 else
|
Chris@16
|
228 {
|
Chris@16
|
229 ec.assign( err, BOOST_CHRONO_SYSTEM_CATEGORY );
|
Chris@16
|
230 return time_point();
|
Chris@16
|
231 }
|
Chris@16
|
232 }
|
Chris@16
|
233 if (!BOOST_CHRONO_IS_THROWS(ec))
|
Chris@16
|
234 {
|
Chris@16
|
235 ec.clear();
|
Chris@16
|
236 }
|
Chris@16
|
237 return time_point(duration(fp(ec)));
|
Chris@16
|
238 }
|
Chris@16
|
239 #endif
|
Chris@16
|
240 } // namespace chrono
|
Chris@16
|
241 } // namespace boost
|