Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:28:40

0001 //
0002 // detail/impl/handler_tracking.ipp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 
0020 #if defined(BOOST_ASIO_CUSTOM_HANDLER_TRACKING)
0021 
0022 // The handler tracking implementation is provided by the user-specified header.
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 // !defined(BOOST_ASIO_WINDOWS)
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 /*native_handle*/, 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 // defined(BOOST_ASIO_WINDOWS)
0129         "@asio|%llu.%06llu|%llu^%llu|%s%s%.80s%s(%.80s:%d)\n",
0130 #endif // defined(BOOST_ASIO_WINDOWS)
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 // defined(BOOST_ASIO_WINDOWS)
0144       "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n",
0145 #endif // defined(BOOST_ASIO_WINDOWS)
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 // defined(BOOST_ASIO_WINDOWS)
0169         "@asio|%llu.%06llu|%c%llu|\n",
0170 #endif // defined(BOOST_ASIO_WINDOWS)
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 // defined(BOOST_ASIO_WINDOWS)
0186       "@asio|%llu.%06llu|>%llu|\n",
0187 #endif // defined(BOOST_ASIO_WINDOWS)
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 // defined(BOOST_ASIO_WINDOWS)
0202       "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n",
0203 #endif // defined(BOOST_ASIO_WINDOWS)
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 // defined(BOOST_ASIO_WINDOWS)
0219       "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n",
0220 #endif // defined(BOOST_ASIO_WINDOWS)
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 // defined(BOOST_ASIO_WINDOWS)
0237       "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n",
0238 #endif // defined(BOOST_ASIO_WINDOWS)
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 // defined(BOOST_ASIO_WINDOWS)
0254       "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n",
0255 #endif // defined(BOOST_ASIO_WINDOWS)
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 // defined(BOOST_ASIO_WINDOWS)
0272         "@asio|%llu.%06llu|<%llu|\n",
0273 #endif // defined(BOOST_ASIO_WINDOWS)
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 /*native_handle*/, 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 // defined(BOOST_ASIO_WINDOWS)
0296       "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n",
0297 #endif // defined(BOOST_ASIO_WINDOWS)
0298       timestamp.seconds, timestamp.microseconds,
0299       current_id, object_type, object, op_name);
0300 }
0301 
0302 void handler_tracking::reactor_registration(execution_context& /*context*/,
0303     uintmax_t /*native_handle*/, uintmax_t /*registration*/)
0304 {
0305 }
0306 
0307 void handler_tracking::reactor_deregistration(execution_context& /*context*/,
0308     uintmax_t /*native_handle*/, uintmax_t /*registration*/)
0309 {
0310 }
0311 
0312 void handler_tracking::reactor_events(execution_context& /*context*/,
0313     uintmax_t /*native_handle*/, unsigned /*events*/)
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 // defined(BOOST_ASIO_WINDOWS)
0327       "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d\n",
0328 #endif // defined(BOOST_ASIO_WINDOWS)
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 // defined(BOOST_ASIO_WINDOWS)
0343       "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d,bytes_transferred=%llu\n",
0344 #endif // defined(BOOST_ASIO_WINDOWS)
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; // For sprintf (or equivalent).
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 // defined(BOOST_ASIO_HAS_SECURE_RTL)
0363   int length = vsprintf(line, format, args);
0364 #endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
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 // defined(BOOST_ASIO_WINDOWS)
0377   ::write(STDERR_FILENO, line, length);
0378 #endif // defined(BOOST_ASIO_WINDOWS)
0379 }
0380 
0381 } // namespace detail
0382 } // namespace asio
0383 } // namespace boost
0384 
0385 #include <boost/asio/detail/pop_options.hpp>
0386 
0387 #endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0388 
0389 #endif // BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP