]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // detail/impl/handler_tracking.ipp | |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
4 | // | |
f67539c2 | 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | ||
11 | #ifndef BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP | |
12 | #define BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP | |
13 | ||
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) | |
15 | # pragma once | |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | |
17 | ||
18 | #include <boost/asio/detail/config.hpp> | |
19 | ||
b32b8144 FG |
20 | #if defined(BOOST_ASIO_CUSTOM_HANDLER_TRACKING) |
21 | ||
22 | // The handler tracking implementation is provided by the user-specified header. | |
23 | ||
24 | #elif defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING) | |
7c673cae FG |
25 | |
26 | #include <cstdarg> | |
27 | #include <cstdio> | |
28 | #include <boost/asio/detail/handler_tracking.hpp> | |
29 | ||
30 | #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) | |
31 | # include <boost/asio/time_traits.hpp> | |
b32b8144 FG |
32 | #elif defined(BOOST_ASIO_HAS_CHRONO) |
33 | # include <boost/asio/detail/chrono.hpp> | |
7c673cae FG |
34 | # include <boost/asio/detail/chrono_time_traits.hpp> |
35 | # include <boost/asio/wait_traits.hpp> | |
36 | #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) | |
37 | ||
b32b8144 FG |
38 | #if defined(BOOST_ASIO_WINDOWS_RUNTIME) |
39 | # include <boost/asio/detail/socket_types.hpp> | |
40 | #elif !defined(BOOST_ASIO_WINDOWS) | |
7c673cae FG |
41 | # include <unistd.h> |
42 | #endif // !defined(BOOST_ASIO_WINDOWS) | |
43 | ||
44 | #include <boost/asio/detail/push_options.hpp> | |
45 | ||
46 | namespace boost { | |
47 | namespace asio { | |
48 | namespace detail { | |
49 | ||
50 | struct handler_tracking_timestamp | |
51 | { | |
52 | uint64_t seconds; | |
53 | uint64_t microseconds; | |
54 | ||
55 | handler_tracking_timestamp() | |
56 | { | |
57 | #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) | |
58 | boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1)); | |
59 | boost::posix_time::time_duration now = | |
60 | boost::posix_time::microsec_clock::universal_time() - epoch; | |
b32b8144 FG |
61 | #elif defined(BOOST_ASIO_HAS_CHRONO) |
62 | typedef chrono_time_traits<chrono::system_clock, | |
63 | boost::asio::wait_traits<chrono::system_clock> > traits_helper; | |
7c673cae | 64 | traits_helper::posix_time_duration now( |
b32b8144 | 65 | chrono::system_clock::now().time_since_epoch()); |
7c673cae FG |
66 | #endif |
67 | seconds = static_cast<uint64_t>(now.total_seconds()); | |
68 | microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000); | |
69 | } | |
70 | }; | |
71 | ||
72 | struct handler_tracking::tracking_state | |
73 | { | |
74 | static_mutex mutex_; | |
75 | uint64_t next_id_; | |
76 | tss_ptr<completion>* current_completion_; | |
77 | }; | |
78 | ||
79 | handler_tracking::tracking_state* handler_tracking::get_state() | |
80 | { | |
81 | static tracking_state state = { BOOST_ASIO_STATIC_MUTEX_INIT, 1, 0 }; | |
82 | return &state; | |
83 | } | |
84 | ||
85 | void handler_tracking::init() | |
86 | { | |
87 | static tracking_state* state = get_state(); | |
88 | ||
89 | state->mutex_.init(); | |
90 | ||
91 | static_mutex::scoped_lock lock(state->mutex_); | |
92 | if (state->current_completion_ == 0) | |
93 | state->current_completion_ = new tss_ptr<completion>; | |
94 | } | |
95 | ||
b32b8144 FG |
96 | void handler_tracking::creation(execution_context&, |
97 | handler_tracking::tracked_handler& h, | |
98 | const char* object_type, void* object, | |
99 | uintmax_t /*native_handle*/, const char* op_name) | |
7c673cae FG |
100 | { |
101 | static tracking_state* state = get_state(); | |
102 | ||
103 | static_mutex::scoped_lock lock(state->mutex_); | |
b32b8144 | 104 | h.id_ = state->next_id_++; |
7c673cae FG |
105 | lock.unlock(); |
106 | ||
107 | handler_tracking_timestamp timestamp; | |
108 | ||
109 | uint64_t current_id = 0; | |
110 | if (completion* current_completion = *state->current_completion_) | |
111 | current_id = current_completion->id_; | |
112 | ||
113 | write_line( | |
114 | #if defined(BOOST_ASIO_WINDOWS) | |
115 | "@asio|%I64u.%06I64u|%I64u*%I64u|%.20s@%p.%.50s\n", | |
116 | #else // defined(BOOST_ASIO_WINDOWS) | |
117 | "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n", | |
118 | #endif // defined(BOOST_ASIO_WINDOWS) | |
119 | timestamp.seconds, timestamp.microseconds, | |
b32b8144 | 120 | current_id, h.id_, object_type, object, op_name); |
7c673cae FG |
121 | } |
122 | ||
b32b8144 FG |
123 | handler_tracking::completion::completion( |
124 | const handler_tracking::tracked_handler& h) | |
125 | : id_(h.id_), | |
7c673cae FG |
126 | invoked_(false), |
127 | next_(*get_state()->current_completion_) | |
128 | { | |
129 | *get_state()->current_completion_ = this; | |
130 | } | |
131 | ||
132 | handler_tracking::completion::~completion() | |
133 | { | |
134 | if (id_) | |
135 | { | |
136 | handler_tracking_timestamp timestamp; | |
137 | ||
138 | write_line( | |
139 | #if defined(BOOST_ASIO_WINDOWS) | |
140 | "@asio|%I64u.%06I64u|%c%I64u|\n", | |
141 | #else // defined(BOOST_ASIO_WINDOWS) | |
142 | "@asio|%llu.%06llu|%c%llu|\n", | |
143 | #endif // defined(BOOST_ASIO_WINDOWS) | |
144 | timestamp.seconds, timestamp.microseconds, | |
145 | invoked_ ? '!' : '~', id_); | |
146 | } | |
147 | ||
148 | *get_state()->current_completion_ = next_; | |
149 | } | |
150 | ||
151 | void handler_tracking::completion::invocation_begin() | |
152 | { | |
153 | handler_tracking_timestamp timestamp; | |
154 | ||
155 | write_line( | |
156 | #if defined(BOOST_ASIO_WINDOWS) | |
157 | "@asio|%I64u.%06I64u|>%I64u|\n", | |
158 | #else // defined(BOOST_ASIO_WINDOWS) | |
159 | "@asio|%llu.%06llu|>%llu|\n", | |
160 | #endif // defined(BOOST_ASIO_WINDOWS) | |
161 | timestamp.seconds, timestamp.microseconds, id_); | |
162 | ||
163 | invoked_ = true; | |
164 | } | |
165 | ||
166 | void handler_tracking::completion::invocation_begin( | |
167 | const boost::system::error_code& ec) | |
168 | { | |
169 | handler_tracking_timestamp timestamp; | |
170 | ||
171 | write_line( | |
172 | #if defined(BOOST_ASIO_WINDOWS) | |
173 | "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d\n", | |
174 | #else // defined(BOOST_ASIO_WINDOWS) | |
175 | "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n", | |
176 | #endif // defined(BOOST_ASIO_WINDOWS) | |
177 | timestamp.seconds, timestamp.microseconds, | |
178 | id_, ec.category().name(), ec.value()); | |
179 | ||
180 | invoked_ = true; | |
181 | } | |
182 | ||
183 | void handler_tracking::completion::invocation_begin( | |
184 | const boost::system::error_code& ec, std::size_t bytes_transferred) | |
185 | { | |
186 | handler_tracking_timestamp timestamp; | |
187 | ||
188 | write_line( | |
189 | #if defined(BOOST_ASIO_WINDOWS) | |
190 | "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,bytes_transferred=%I64u\n", | |
191 | #else // defined(BOOST_ASIO_WINDOWS) | |
192 | "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n", | |
193 | #endif // defined(BOOST_ASIO_WINDOWS) | |
194 | timestamp.seconds, timestamp.microseconds, | |
195 | id_, ec.category().name(), ec.value(), | |
196 | static_cast<uint64_t>(bytes_transferred)); | |
197 | ||
198 | invoked_ = true; | |
199 | } | |
200 | ||
201 | void handler_tracking::completion::invocation_begin( | |
202 | const boost::system::error_code& ec, int signal_number) | |
203 | { | |
204 | handler_tracking_timestamp timestamp; | |
205 | ||
206 | write_line( | |
207 | #if defined(BOOST_ASIO_WINDOWS) | |
208 | "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,signal_number=%d\n", | |
209 | #else // defined(BOOST_ASIO_WINDOWS) | |
210 | "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n", | |
211 | #endif // defined(BOOST_ASIO_WINDOWS) | |
212 | timestamp.seconds, timestamp.microseconds, | |
213 | id_, ec.category().name(), ec.value(), signal_number); | |
214 | ||
215 | invoked_ = true; | |
216 | } | |
217 | ||
218 | void handler_tracking::completion::invocation_begin( | |
219 | const boost::system::error_code& ec, const char* arg) | |
220 | { | |
221 | handler_tracking_timestamp timestamp; | |
222 | ||
223 | write_line( | |
224 | #if defined(BOOST_ASIO_WINDOWS) | |
225 | "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,%.50s\n", | |
226 | #else // defined(BOOST_ASIO_WINDOWS) | |
227 | "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n", | |
228 | #endif // defined(BOOST_ASIO_WINDOWS) | |
229 | timestamp.seconds, timestamp.microseconds, | |
230 | id_, ec.category().name(), ec.value(), arg); | |
231 | ||
232 | invoked_ = true; | |
233 | } | |
234 | ||
235 | void handler_tracking::completion::invocation_end() | |
236 | { | |
237 | if (id_) | |
238 | { | |
239 | handler_tracking_timestamp timestamp; | |
240 | ||
241 | write_line( | |
242 | #if defined(BOOST_ASIO_WINDOWS) | |
243 | "@asio|%I64u.%06I64u|<%I64u|\n", | |
244 | #else // defined(BOOST_ASIO_WINDOWS) | |
245 | "@asio|%llu.%06llu|<%llu|\n", | |
246 | #endif // defined(BOOST_ASIO_WINDOWS) | |
247 | timestamp.seconds, timestamp.microseconds, id_); | |
248 | ||
249 | id_ = 0; | |
250 | } | |
251 | } | |
252 | ||
b32b8144 FG |
253 | void handler_tracking::operation(execution_context&, |
254 | const char* object_type, void* object, | |
255 | uintmax_t /*native_handle*/, const char* op_name) | |
7c673cae FG |
256 | { |
257 | static tracking_state* state = get_state(); | |
258 | ||
259 | handler_tracking_timestamp timestamp; | |
260 | ||
261 | unsigned long long current_id = 0; | |
262 | if (completion* current_completion = *state->current_completion_) | |
263 | current_id = current_completion->id_; | |
264 | ||
265 | write_line( | |
266 | #if defined(BOOST_ASIO_WINDOWS) | |
267 | "@asio|%I64u.%06I64u|%I64u|%.20s@%p.%.50s\n", | |
268 | #else // defined(BOOST_ASIO_WINDOWS) | |
269 | "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n", | |
270 | #endif // defined(BOOST_ASIO_WINDOWS) | |
271 | timestamp.seconds, timestamp.microseconds, | |
272 | current_id, object_type, object, op_name); | |
273 | } | |
274 | ||
b32b8144 FG |
275 | void handler_tracking::reactor_registration(execution_context& /*context*/, |
276 | uintmax_t /*native_handle*/, uintmax_t /*registration*/) | |
277 | { | |
278 | } | |
279 | ||
280 | void handler_tracking::reactor_deregistration(execution_context& /*context*/, | |
281 | uintmax_t /*native_handle*/, uintmax_t /*registration*/) | |
282 | { | |
283 | } | |
284 | ||
285 | void handler_tracking::reactor_events(execution_context& /*context*/, | |
286 | uintmax_t /*native_handle*/, unsigned /*events*/) | |
287 | { | |
288 | } | |
289 | ||
290 | void handler_tracking::reactor_operation( | |
291 | const tracked_handler& h, const char* op_name, | |
292 | const boost::system::error_code& ec) | |
293 | { | |
294 | handler_tracking_timestamp timestamp; | |
295 | ||
296 | write_line( | |
297 | #if defined(BOOST_ASIO_WINDOWS) | |
298 | "@asio|%I64u.%06I64u|.%I64u|%s,ec=%.20s:%d\n", | |
299 | #else // defined(BOOST_ASIO_WINDOWS) | |
300 | "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d\n", | |
301 | #endif // defined(BOOST_ASIO_WINDOWS) | |
302 | timestamp.seconds, timestamp.microseconds, | |
303 | h.id_, op_name, ec.category().name(), ec.value()); | |
304 | } | |
305 | ||
306 | void handler_tracking::reactor_operation( | |
307 | const tracked_handler& h, const char* op_name, | |
308 | const boost::system::error_code& ec, std::size_t bytes_transferred) | |
309 | { | |
310 | handler_tracking_timestamp timestamp; | |
311 | ||
312 | write_line( | |
313 | #if defined(BOOST_ASIO_WINDOWS) | |
314 | "@asio|%I64u.%06I64u|.%I64u|%s,ec=%.20s:%d,bytes_transferred=%I64u\n", | |
315 | #else // defined(BOOST_ASIO_WINDOWS) | |
316 | "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d,bytes_transferred=%llu\n", | |
317 | #endif // defined(BOOST_ASIO_WINDOWS) | |
318 | timestamp.seconds, timestamp.microseconds, | |
319 | h.id_, op_name, ec.category().name(), ec.value(), | |
320 | static_cast<uint64_t>(bytes_transferred)); | |
321 | } | |
322 | ||
7c673cae FG |
323 | void handler_tracking::write_line(const char* format, ...) |
324 | { | |
325 | using namespace std; // For sprintf (or equivalent). | |
326 | ||
327 | va_list args; | |
328 | va_start(args, format); | |
329 | ||
330 | char line[256] = ""; | |
331 | #if defined(BOOST_ASIO_HAS_SECURE_RTL) | |
332 | int length = vsprintf_s(line, sizeof(line), format, args); | |
333 | #else // defined(BOOST_ASIO_HAS_SECURE_RTL) | |
334 | int length = vsprintf(line, format, args); | |
335 | #endif // defined(BOOST_ASIO_HAS_SECURE_RTL) | |
336 | ||
337 | va_end(args); | |
338 | ||
b32b8144 FG |
339 | #if defined(BOOST_ASIO_WINDOWS_RUNTIME) |
340 | wchar_t wline[256] = L""; | |
341 | mbstowcs_s(0, wline, sizeof(wline) / sizeof(wchar_t), line, length); | |
342 | ::OutputDebugStringW(wline); | |
343 | #elif defined(BOOST_ASIO_WINDOWS) | |
7c673cae FG |
344 | HANDLE stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE); |
345 | DWORD bytes_written = 0; | |
346 | ::WriteFile(stderr_handle, line, length, &bytes_written, 0); | |
347 | #else // defined(BOOST_ASIO_WINDOWS) | |
348 | ::write(STDERR_FILENO, line, length); | |
349 | #endif // defined(BOOST_ASIO_WINDOWS) | |
350 | } | |
351 | ||
352 | } // namespace detail | |
353 | } // namespace asio | |
354 | } // namespace boost | |
355 | ||
356 | #include <boost/asio/detail/pop_options.hpp> | |
357 | ||
358 | #endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING) | |
359 | ||
360 | #endif // BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP |