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