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