]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/timer/src/cpu_timer.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / timer / src / cpu_timer.cpp
CommitLineData
7c673cae
FG
1// boost cpu_timer.cpp ---------------------------------------------------------------//
2
3// Copyright Beman Dawes 1994-2006, 2011
4
5// Distributed under the Boost Software License, Version 1.0. (See accompanying
6// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8// See http://www.boost.org/libs/timer for documentation.
9
10//--------------------------------------------------------------------------------------//
11
12// define BOOST_TIMER_SOURCE so that <boost/timer/config.hpp> knows
13// the library is being built (possibly exporting rather than importing code)
14#define BOOST_TIMER_SOURCE
15
16#include <boost/timer/timer.hpp>
17#include <boost/chrono/chrono.hpp>
18#include <boost/io/ios_state.hpp>
19#include <boost/throw_exception.hpp>
20#include <boost/cerrno.hpp>
21#include <cstring>
22#include <sstream>
23#include <cassert>
24
25# if defined(BOOST_WINDOWS_API)
26# include <windows.h>
27# elif defined(BOOST_POSIX_API)
28# include <unistd.h>
29# include <sys/times.h>
30# else
31# error unknown API
32# endif
33
34using boost::timer::nanosecond_type;
35using boost::timer::cpu_times;
36using boost::system::error_code;
37
38namespace
39{
40
41 void show_time(const cpu_times& times,
42 std::ostream& os, const std::string& fmt, short places)
43 // NOTE WELL: Will truncate least-significant digits to LDBL_DIG, which may
44 // be as low as 10, although will be 15 for many common platforms.
45 {
46 if (places > 9)
47 places = 9;
48 else if (places < 0)
49 places = boost::timer::default_places;
50
51 boost::io::ios_flags_saver ifs(os);
52 boost::io::ios_precision_saver ips(os);
53 os.setf(std::ios_base::fixed, std::ios_base::floatfield);
54 os.precision(places);
55
56 const double sec = 1000000000.0L;
57 nanosecond_type total = times.system + times.user;
58 double wall_sec = static_cast<double>(times.wall) / sec;
59 double total_sec = static_cast<double>(total) / sec;
60
61 for (const char* format = fmt.c_str(); *format; ++format)
62 {
63 if (*format != '%' || !*(format+1) || !std::strchr("wustp", *(format+1)))
64 os << *format; // anything except % followed by a valid format character
65 // gets sent to the output stream
66 else
67 {
68 ++format;
69 switch (*format)
70 {
71 case 'w':
72 os << wall_sec;
73 break;
74 case 'u':
75 os << static_cast<double>(times.user) / sec;
76 break;
77 case 's':
78 os << static_cast<double>(times.system) / sec;
79 break;
80 case 't':
81 os << total_sec;
82 break;
83 case 'p':
84 os.precision(1);
85 if (wall_sec > 0.001L && total_sec > 0.001L)
86 os << (total_sec/wall_sec) * 100.0;
87 else
88 os << "n/a";
89 os.precision(places);
90 break;
91 }
92 }
93 }
94 }
95
96# if defined(BOOST_POSIX_API)
97 boost::int_least64_t tick_factor() // multiplier to convert ticks
98 // to nanoseconds; -1 if unknown
99 {
100 static boost::int_least64_t tick_factor = 0;
101 if (!tick_factor)
102 {
103 if ((tick_factor = ::sysconf(_SC_CLK_TCK)) <= 0)
104 tick_factor = -1;
105 else
106 {
b32b8144
FG
107 assert(tick_factor <= INT64_C(1000000000)); // logic doesn't handle large ticks
108 tick_factor = INT64_C(1000000000) / tick_factor; // compute factor
7c673cae
FG
109 if (!tick_factor)
110 tick_factor = -1;
111 }
112 }
113 return tick_factor;
114 }
115# endif
116
117 void get_cpu_times(boost::timer::cpu_times& current)
118 {
119 boost::chrono::duration<boost::int64_t, boost::nano>
120 x (boost::chrono::high_resolution_clock::now().time_since_epoch());
121 current.wall = x.count();
122
123# if defined(BOOST_WINDOWS_API)
124
125 FILETIME creation, exit;
126 if (::GetProcessTimes(::GetCurrentProcess(), &creation, &exit,
127 (LPFILETIME)&current.system, (LPFILETIME)&current.user))
128 {
129 current.user *= 100; // Windows uses 100 nanosecond ticks
130 current.system *= 100;
131 }
132 else
133 {
134 current.system = current.user = boost::timer::nanosecond_type(-1);
135 }
136# else
137 tms tm;
138 clock_t c = ::times(&tm);
139 if (c == static_cast<clock_t>(-1)) // error
140 {
141 current.system = current.user = boost::timer::nanosecond_type(-1);
142 }
143 else
144 {
145 current.system = boost::timer::nanosecond_type(tm.tms_stime + tm.tms_cstime);
146 current.user = boost::timer::nanosecond_type(tm.tms_utime + tm.tms_cutime);
147 boost::int_least64_t factor;
148 if ((factor = tick_factor()) != -1)
149 {
150 current.user *= factor;
151 current.system *= factor;
152 }
153 else
154 {
155 current.user = current.system = boost::timer::nanosecond_type(-1);
156 }
157 }
158# endif
159 }
160
161 // CAUTION: must be identical to same constant in auto_timers_construction.cpp
162 const std::string default_fmt(" %ws wall, %us user + %ss system = %ts CPU (%p%)\n");
163
164} // unnamed namespace
165
166namespace boost
167{
168 namespace timer
169 {
170 // format ------------------------------------------------------------------------//
171
172 BOOST_TIMER_DECL
173 std::string format(const cpu_times& times, short places, const std::string& fmt)
174 {
175 std::stringstream ss;
176 ss.exceptions(std::ios_base::badbit | std::ios_base::failbit);
177 show_time(times, ss, fmt, places);
178 return ss.str();
179 }
180
181 BOOST_TIMER_DECL
182 std::string format(const cpu_times& times, short places)
183 {
184 return format(times, places, default_fmt);
185 }
186
187 // cpu_timer ---------------------------------------------------------------------//
188
189 void cpu_timer::start() BOOST_NOEXCEPT
190 {
191 m_is_stopped = false;
192 get_cpu_times(m_times);
193 }
194
195 void cpu_timer::stop() BOOST_NOEXCEPT
196 {
197 if (is_stopped())
198 return;
199 m_is_stopped = true;
200
201 cpu_times current;
202 get_cpu_times(current);
203 m_times.wall = (current.wall - m_times.wall);
204 m_times.user = (current.user - m_times.user);
205 m_times.system = (current.system - m_times.system);
206 }
207
208 cpu_times cpu_timer::elapsed() const BOOST_NOEXCEPT
209 {
210 if (is_stopped())
211 return m_times;
212 cpu_times current;
213 get_cpu_times(current);
214 current.wall -= m_times.wall;
215 current.user -= m_times.user;
216 current.system -= m_times.system;
217 return current;
218 }
219
220 void cpu_timer::resume() BOOST_NOEXCEPT
221 {
222 if (is_stopped())
223 {
224 cpu_times current (m_times);
225 start();
226 m_times.wall -= current.wall;
227 m_times.user -= current.user;
228 m_times.system -= current.system;
229 }
230 }
231
232 // auto_cpu_timer ----------------------------------------------------------------//
233
234 auto_cpu_timer::auto_cpu_timer(std::ostream& os, short places) // #5
235 : m_places(places), m_os(&os), m_format(default_fmt)
236 {
237 start();
238 }
239
240 void auto_cpu_timer::report()
241 {
242 show_time(elapsed(), ostream(), format_string(), places());
243 }
244
245 auto_cpu_timer::~auto_cpu_timer()
246 {
247 if (!is_stopped())
248 {
249 stop(); // the sooner we stop(), the better
b32b8144 250#ifndef BOOST_NO_EXCEPTIONS
7c673cae
FG
251 try
252 {
b32b8144 253#endif
7c673cae 254 report();
b32b8144 255#ifndef BOOST_NO_EXCEPTIONS
7c673cae
FG
256 }
257 catch (...) // eat any exceptions
258 {
259 }
b32b8144 260#endif
7c673cae
FG
261 }
262 }
263
264 } // namespace timer
265} // namespace boost