File indexing completed on 2025-09-16 08:28:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP
0012 #define BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019
0020 #if defined(BOOST_ASIO_CUSTOM_HANDLER_TRACKING)
0021
0022
0023
0024 #elif defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0025
0026 #include <cstdarg>
0027 #include <cstdio>
0028 #include <boost/asio/detail/chrono.hpp>
0029 #include <boost/asio/detail/chrono_time_traits.hpp>
0030 #include <boost/asio/detail/handler_tracking.hpp>
0031 #include <boost/asio/wait_traits.hpp>
0032
0033 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
0034 # include <boost/asio/detail/socket_types.hpp>
0035 #elif !defined(BOOST_ASIO_WINDOWS)
0036 # include <unistd.h>
0037 #endif
0038
0039 #include <boost/asio/detail/push_options.hpp>
0040
0041 namespace boost {
0042 namespace asio {
0043 namespace detail {
0044
0045 struct handler_tracking_timestamp
0046 {
0047 uint64_t seconds;
0048 uint64_t microseconds;
0049
0050 handler_tracking_timestamp()
0051 {
0052 typedef chrono_time_traits<chrono::system_clock,
0053 boost::asio::wait_traits<chrono::system_clock>> traits_helper;
0054 traits_helper::posix_time_duration now(
0055 chrono::system_clock::now().time_since_epoch());
0056 seconds = static_cast<uint64_t>(now.total_seconds());
0057 microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000);
0058 }
0059 };
0060
0061 struct handler_tracking::tracking_state
0062 {
0063 static_mutex mutex_;
0064 uint64_t next_id_;
0065 tss_ptr<completion>* current_completion_;
0066 tss_ptr<location>* current_location_;
0067 };
0068
0069 handler_tracking::tracking_state* handler_tracking::get_state()
0070 {
0071 static tracking_state state = { BOOST_ASIO_STATIC_MUTEX_INIT, 1, 0, 0 };
0072 return &state;
0073 }
0074
0075 void handler_tracking::init()
0076 {
0077 static tracking_state* state = get_state();
0078
0079 state->mutex_.init();
0080
0081 static_mutex::scoped_lock lock(state->mutex_);
0082 if (state->current_completion_ == 0)
0083 state->current_completion_ = new tss_ptr<completion>;
0084 if (state->current_location_ == 0)
0085 state->current_location_ = new tss_ptr<location>;
0086 }
0087
0088 handler_tracking::location::location(
0089 const char* file, int line, const char* func)
0090 : file_(file),
0091 line_(line),
0092 func_(func),
0093 next_(*get_state()->current_location_)
0094 {
0095 if (file_)
0096 *get_state()->current_location_ = this;
0097 }
0098
0099 handler_tracking::location::~location()
0100 {
0101 if (file_)
0102 *get_state()->current_location_ = next_;
0103 }
0104
0105 void handler_tracking::creation(execution_context&,
0106 handler_tracking::tracked_handler& h,
0107 const char* object_type, void* object,
0108 uintmax_t , const char* op_name)
0109 {
0110 static tracking_state* state = get_state();
0111
0112 static_mutex::scoped_lock lock(state->mutex_);
0113 h.id_ = state->next_id_++;
0114 lock.unlock();
0115
0116 handler_tracking_timestamp timestamp;
0117
0118 uint64_t current_id = 0;
0119 if (completion* current_completion = *state->current_completion_)
0120 current_id = current_completion->id_;
0121
0122 for (location* current_location = *state->current_location_;
0123 current_location; current_location = current_location->next_)
0124 {
0125 write_line(
0126 #if defined(BOOST_ASIO_WINDOWS)
0127 "@asio|%I64u.%06I64u|%I64u^%I64u|%s%s%.80s%s(%.80s:%d)\n",
0128 #else
0129 "@asio|%llu.%06llu|%llu^%llu|%s%s%.80s%s(%.80s:%d)\n",
0130 #endif
0131 timestamp.seconds, timestamp.microseconds,
0132 current_id, h.id_,
0133 current_location == *state->current_location_ ? "in " : "called from ",
0134 current_location->func_ ? "'" : "",
0135 current_location->func_ ? current_location->func_ : "",
0136 current_location->func_ ? "' " : "",
0137 current_location->file_, current_location->line_);
0138 }
0139
0140 write_line(
0141 #if defined(BOOST_ASIO_WINDOWS)
0142 "@asio|%I64u.%06I64u|%I64u*%I64u|%.20s@%p.%.50s\n",
0143 #else
0144 "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n",
0145 #endif
0146 timestamp.seconds, timestamp.microseconds,
0147 current_id, h.id_, object_type, object, op_name);
0148 }
0149
0150 handler_tracking::completion::completion(
0151 const handler_tracking::tracked_handler& h)
0152 : id_(h.id_),
0153 invoked_(false),
0154 next_(*get_state()->current_completion_)
0155 {
0156 *get_state()->current_completion_ = this;
0157 }
0158
0159 handler_tracking::completion::~completion()
0160 {
0161 if (id_)
0162 {
0163 handler_tracking_timestamp timestamp;
0164
0165 write_line(
0166 #if defined(BOOST_ASIO_WINDOWS)
0167 "@asio|%I64u.%06I64u|%c%I64u|\n",
0168 #else
0169 "@asio|%llu.%06llu|%c%llu|\n",
0170 #endif
0171 timestamp.seconds, timestamp.microseconds,
0172 invoked_ ? '!' : '~', id_);
0173 }
0174
0175 *get_state()->current_completion_ = next_;
0176 }
0177
0178 void handler_tracking::completion::invocation_begin()
0179 {
0180 handler_tracking_timestamp timestamp;
0181
0182 write_line(
0183 #if defined(BOOST_ASIO_WINDOWS)
0184 "@asio|%I64u.%06I64u|>%I64u|\n",
0185 #else
0186 "@asio|%llu.%06llu|>%llu|\n",
0187 #endif
0188 timestamp.seconds, timestamp.microseconds, id_);
0189
0190 invoked_ = true;
0191 }
0192
0193 void handler_tracking::completion::invocation_begin(
0194 const boost::system::error_code& ec)
0195 {
0196 handler_tracking_timestamp timestamp;
0197
0198 write_line(
0199 #if defined(BOOST_ASIO_WINDOWS)
0200 "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d\n",
0201 #else
0202 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n",
0203 #endif
0204 timestamp.seconds, timestamp.microseconds,
0205 id_, ec.category().name(), ec.value());
0206
0207 invoked_ = true;
0208 }
0209
0210 void handler_tracking::completion::invocation_begin(
0211 const boost::system::error_code& ec, std::size_t bytes_transferred)
0212 {
0213 handler_tracking_timestamp timestamp;
0214
0215 write_line(
0216 #if defined(BOOST_ASIO_WINDOWS)
0217 "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,bytes_transferred=%I64u\n",
0218 #else
0219 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n",
0220 #endif
0221 timestamp.seconds, timestamp.microseconds,
0222 id_, ec.category().name(), ec.value(),
0223 static_cast<uint64_t>(bytes_transferred));
0224
0225 invoked_ = true;
0226 }
0227
0228 void handler_tracking::completion::invocation_begin(
0229 const boost::system::error_code& ec, int signal_number)
0230 {
0231 handler_tracking_timestamp timestamp;
0232
0233 write_line(
0234 #if defined(BOOST_ASIO_WINDOWS)
0235 "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,signal_number=%d\n",
0236 #else
0237 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n",
0238 #endif
0239 timestamp.seconds, timestamp.microseconds,
0240 id_, ec.category().name(), ec.value(), signal_number);
0241
0242 invoked_ = true;
0243 }
0244
0245 void handler_tracking::completion::invocation_begin(
0246 const boost::system::error_code& ec, const char* arg)
0247 {
0248 handler_tracking_timestamp timestamp;
0249
0250 write_line(
0251 #if defined(BOOST_ASIO_WINDOWS)
0252 "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,%.50s\n",
0253 #else
0254 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n",
0255 #endif
0256 timestamp.seconds, timestamp.microseconds,
0257 id_, ec.category().name(), ec.value(), arg);
0258
0259 invoked_ = true;
0260 }
0261
0262 void handler_tracking::completion::invocation_end()
0263 {
0264 if (id_)
0265 {
0266 handler_tracking_timestamp timestamp;
0267
0268 write_line(
0269 #if defined(BOOST_ASIO_WINDOWS)
0270 "@asio|%I64u.%06I64u|<%I64u|\n",
0271 #else
0272 "@asio|%llu.%06llu|<%llu|\n",
0273 #endif
0274 timestamp.seconds, timestamp.microseconds, id_);
0275
0276 id_ = 0;
0277 }
0278 }
0279
0280 void handler_tracking::operation(execution_context&,
0281 const char* object_type, void* object,
0282 uintmax_t , const char* op_name)
0283 {
0284 static tracking_state* state = get_state();
0285
0286 handler_tracking_timestamp timestamp;
0287
0288 unsigned long long current_id = 0;
0289 if (completion* current_completion = *state->current_completion_)
0290 current_id = current_completion->id_;
0291
0292 write_line(
0293 #if defined(BOOST_ASIO_WINDOWS)
0294 "@asio|%I64u.%06I64u|%I64u|%.20s@%p.%.50s\n",
0295 #else
0296 "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n",
0297 #endif
0298 timestamp.seconds, timestamp.microseconds,
0299 current_id, object_type, object, op_name);
0300 }
0301
0302 void handler_tracking::reactor_registration(execution_context& ,
0303 uintmax_t , uintmax_t )
0304 {
0305 }
0306
0307 void handler_tracking::reactor_deregistration(execution_context& ,
0308 uintmax_t , uintmax_t )
0309 {
0310 }
0311
0312 void handler_tracking::reactor_events(execution_context& ,
0313 uintmax_t , unsigned )
0314 {
0315 }
0316
0317 void handler_tracking::reactor_operation(
0318 const tracked_handler& h, const char* op_name,
0319 const boost::system::error_code& ec)
0320 {
0321 handler_tracking_timestamp timestamp;
0322
0323 write_line(
0324 #if defined(BOOST_ASIO_WINDOWS)
0325 "@asio|%I64u.%06I64u|.%I64u|%s,ec=%.20s:%d\n",
0326 #else
0327 "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d\n",
0328 #endif
0329 timestamp.seconds, timestamp.microseconds,
0330 h.id_, op_name, ec.category().name(), ec.value());
0331 }
0332
0333 void handler_tracking::reactor_operation(
0334 const tracked_handler& h, const char* op_name,
0335 const boost::system::error_code& ec, std::size_t bytes_transferred)
0336 {
0337 handler_tracking_timestamp timestamp;
0338
0339 write_line(
0340 #if defined(BOOST_ASIO_WINDOWS)
0341 "@asio|%I64u.%06I64u|.%I64u|%s,ec=%.20s:%d,bytes_transferred=%I64u\n",
0342 #else
0343 "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d,bytes_transferred=%llu\n",
0344 #endif
0345 timestamp.seconds, timestamp.microseconds,
0346 h.id_, op_name, ec.category().name(), ec.value(),
0347 static_cast<uint64_t>(bytes_transferred));
0348 }
0349
0350 void handler_tracking::write_line(const char* format, ...)
0351 {
0352 using namespace std;
0353
0354 va_list args;
0355 va_start(args, format);
0356
0357 char line[256] = "";
0358 #if defined(BOOST_ASIO_HAS_SNPRINTF)
0359 int length = vsnprintf(line, sizeof(line), format, args);
0360 #elif defined(BOOST_ASIO_HAS_SECURE_RTL)
0361 int length = vsprintf_s(line, sizeof(line), format, args);
0362 #else
0363 int length = vsprintf(line, format, args);
0364 #endif
0365
0366 va_end(args);
0367
0368 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
0369 wchar_t wline[256] = L"";
0370 mbstowcs_s(0, wline, sizeof(wline) / sizeof(wchar_t), line, length);
0371 ::OutputDebugStringW(wline);
0372 #elif defined(BOOST_ASIO_WINDOWS)
0373 HANDLE stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE);
0374 DWORD bytes_written = 0;
0375 ::WriteFile(stderr_handle, line, length, &bytes_written, 0);
0376 #else
0377 ::write(STDERR_FILENO, line, length);
0378 #endif
0379 }
0380
0381 }
0382 }
0383 }
0384
0385 #include <boost/asio/detail/pop_options.hpp>
0386
0387 #endif
0388
0389 #endif