Chris@16: // Chris@16: // detail/impl/handler_tracking.ipp Chris@16: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Chris@16: // Chris@101: // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: Chris@16: #ifndef BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP Chris@16: #define BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP Chris@16: Chris@16: #if defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: # pragma once Chris@16: #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: Chris@16: #include Chris@16: Chris@16: #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) Chris@16: # include Chris@16: #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) Chris@16: # if defined(BOOST_ASIO_HAS_STD_CHRONO) Chris@16: # include Chris@16: # elif defined(BOOST_ASIO_HAS_BOOST_CHRONO) Chris@16: # include Chris@16: # endif Chris@16: # include Chris@16: # include Chris@16: #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) Chris@16: Chris@16: #if !defined(BOOST_ASIO_WINDOWS) Chris@16: # include Chris@16: #endif // !defined(BOOST_ASIO_WINDOWS) Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace asio { Chris@16: namespace detail { Chris@16: Chris@16: struct handler_tracking_timestamp Chris@16: { Chris@16: uint64_t seconds; Chris@16: uint64_t microseconds; Chris@16: Chris@16: handler_tracking_timestamp() Chris@16: { Chris@16: #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) Chris@16: boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1)); Chris@16: boost::posix_time::time_duration now = Chris@16: boost::posix_time::microsec_clock::universal_time() - epoch; Chris@16: #elif defined(BOOST_ASIO_HAS_STD_CHRONO) Chris@16: typedef chrono_time_traits > traits_helper; Chris@16: traits_helper::posix_time_duration now( Chris@16: std::chrono::system_clock::now().time_since_epoch()); Chris@16: #elif defined(BOOST_ASIO_HAS_BOOST_CHRONO) Chris@16: typedef chrono_time_traits > traits_helper; Chris@16: traits_helper::posix_time_duration now( Chris@16: boost::chrono::system_clock::now().time_since_epoch()); Chris@16: #endif Chris@16: seconds = static_cast(now.total_seconds()); Chris@16: microseconds = static_cast(now.total_microseconds() % 1000000); Chris@16: } Chris@16: }; Chris@16: Chris@16: struct handler_tracking::tracking_state Chris@16: { Chris@16: static_mutex mutex_; Chris@16: uint64_t next_id_; Chris@16: tss_ptr* current_completion_; Chris@16: }; Chris@16: Chris@16: handler_tracking::tracking_state* handler_tracking::get_state() Chris@16: { Chris@16: static tracking_state state = { BOOST_ASIO_STATIC_MUTEX_INIT, 1, 0 }; Chris@16: return &state; Chris@16: } Chris@16: Chris@16: void handler_tracking::init() Chris@16: { Chris@16: static tracking_state* state = get_state(); Chris@16: Chris@16: state->mutex_.init(); Chris@16: Chris@16: static_mutex::scoped_lock lock(state->mutex_); Chris@16: if (state->current_completion_ == 0) Chris@16: state->current_completion_ = new tss_ptr; Chris@16: } Chris@16: Chris@16: void handler_tracking::creation(handler_tracking::tracked_handler* h, Chris@16: const char* object_type, void* object, const char* op_name) Chris@16: { Chris@16: static tracking_state* state = get_state(); Chris@16: Chris@16: static_mutex::scoped_lock lock(state->mutex_); Chris@16: h->id_ = state->next_id_++; Chris@16: lock.unlock(); Chris@16: Chris@16: handler_tracking_timestamp timestamp; Chris@16: Chris@16: uint64_t current_id = 0; Chris@16: if (completion* current_completion = *state->current_completion_) Chris@16: current_id = current_completion->id_; Chris@16: Chris@16: write_line( Chris@16: #if defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%I64u.%06I64u|%I64u*%I64u|%.20s@%p.%.50s\n", Chris@16: #else // defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n", Chris@16: #endif // defined(BOOST_ASIO_WINDOWS) Chris@16: timestamp.seconds, timestamp.microseconds, Chris@16: current_id, h->id_, object_type, object, op_name); Chris@16: } Chris@16: Chris@16: handler_tracking::completion::completion(handler_tracking::tracked_handler* h) Chris@16: : id_(h->id_), Chris@16: invoked_(false), Chris@16: next_(*get_state()->current_completion_) Chris@16: { Chris@16: *get_state()->current_completion_ = this; Chris@16: } Chris@16: Chris@16: handler_tracking::completion::~completion() Chris@16: { Chris@16: if (id_) Chris@16: { Chris@16: handler_tracking_timestamp timestamp; Chris@16: Chris@16: write_line( Chris@16: #if defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%I64u.%06I64u|%c%I64u|\n", Chris@16: #else // defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%llu.%06llu|%c%llu|\n", Chris@16: #endif // defined(BOOST_ASIO_WINDOWS) Chris@16: timestamp.seconds, timestamp.microseconds, Chris@16: invoked_ ? '!' : '~', id_); Chris@16: } Chris@16: Chris@16: *get_state()->current_completion_ = next_; Chris@16: } Chris@16: Chris@16: void handler_tracking::completion::invocation_begin() Chris@16: { Chris@16: handler_tracking_timestamp timestamp; Chris@16: Chris@16: write_line( Chris@16: #if defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%I64u.%06I64u|>%I64u|\n", Chris@16: #else // defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%llu.%06llu|>%llu|\n", Chris@16: #endif // defined(BOOST_ASIO_WINDOWS) Chris@16: timestamp.seconds, timestamp.microseconds, id_); Chris@16: Chris@16: invoked_ = true; Chris@16: } Chris@16: Chris@16: void handler_tracking::completion::invocation_begin( Chris@16: const boost::system::error_code& ec) Chris@16: { Chris@16: handler_tracking_timestamp timestamp; Chris@16: Chris@16: write_line( Chris@16: #if defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d\n", Chris@16: #else // defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n", Chris@16: #endif // defined(BOOST_ASIO_WINDOWS) Chris@16: timestamp.seconds, timestamp.microseconds, Chris@16: id_, ec.category().name(), ec.value()); Chris@16: Chris@16: invoked_ = true; Chris@16: } Chris@16: Chris@16: void handler_tracking::completion::invocation_begin( Chris@16: const boost::system::error_code& ec, std::size_t bytes_transferred) Chris@16: { Chris@16: handler_tracking_timestamp timestamp; Chris@16: Chris@16: write_line( Chris@16: #if defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,bytes_transferred=%I64u\n", Chris@16: #else // defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n", Chris@16: #endif // defined(BOOST_ASIO_WINDOWS) Chris@16: timestamp.seconds, timestamp.microseconds, Chris@16: id_, ec.category().name(), ec.value(), Chris@16: static_cast(bytes_transferred)); Chris@16: Chris@16: invoked_ = true; Chris@16: } Chris@16: Chris@16: void handler_tracking::completion::invocation_begin( Chris@16: const boost::system::error_code& ec, int signal_number) Chris@16: { Chris@16: handler_tracking_timestamp timestamp; Chris@16: Chris@16: write_line( Chris@16: #if defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,signal_number=%d\n", Chris@16: #else // defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n", Chris@16: #endif // defined(BOOST_ASIO_WINDOWS) Chris@16: timestamp.seconds, timestamp.microseconds, Chris@16: id_, ec.category().name(), ec.value(), signal_number); Chris@16: Chris@16: invoked_ = true; Chris@16: } Chris@16: Chris@16: void handler_tracking::completion::invocation_begin( Chris@16: const boost::system::error_code& ec, const char* arg) Chris@16: { Chris@16: handler_tracking_timestamp timestamp; Chris@16: Chris@16: write_line( Chris@16: #if defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,%.50s\n", Chris@16: #else // defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n", Chris@16: #endif // defined(BOOST_ASIO_WINDOWS) Chris@16: timestamp.seconds, timestamp.microseconds, Chris@16: id_, ec.category().name(), ec.value(), arg); Chris@16: Chris@16: invoked_ = true; Chris@16: } Chris@16: Chris@16: void handler_tracking::completion::invocation_end() Chris@16: { Chris@16: if (id_) Chris@16: { Chris@16: handler_tracking_timestamp timestamp; Chris@16: Chris@16: write_line( Chris@16: #if defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%I64u.%06I64u|<%I64u|\n", Chris@16: #else // defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%llu.%06llu|<%llu|\n", Chris@16: #endif // defined(BOOST_ASIO_WINDOWS) Chris@16: timestamp.seconds, timestamp.microseconds, id_); Chris@16: Chris@16: id_ = 0; Chris@16: } Chris@16: } Chris@16: Chris@16: void handler_tracking::operation(const char* object_type, Chris@16: void* object, const char* op_name) Chris@16: { Chris@16: static tracking_state* state = get_state(); Chris@16: Chris@16: handler_tracking_timestamp timestamp; Chris@16: Chris@16: unsigned long long current_id = 0; Chris@16: if (completion* current_completion = *state->current_completion_) Chris@16: current_id = current_completion->id_; Chris@16: Chris@16: write_line( Chris@16: #if defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%I64u.%06I64u|%I64u|%.20s@%p.%.50s\n", Chris@16: #else // defined(BOOST_ASIO_WINDOWS) Chris@16: "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n", Chris@16: #endif // defined(BOOST_ASIO_WINDOWS) Chris@16: timestamp.seconds, timestamp.microseconds, Chris@16: current_id, object_type, object, op_name); Chris@16: } Chris@16: Chris@16: void handler_tracking::write_line(const char* format, ...) Chris@16: { Chris@16: using namespace std; // For sprintf (or equivalent). Chris@16: Chris@16: va_list args; Chris@16: va_start(args, format); Chris@16: Chris@16: char line[256] = ""; Chris@16: #if defined(BOOST_ASIO_HAS_SECURE_RTL) Chris@16: int length = vsprintf_s(line, sizeof(line), format, args); Chris@16: #else // defined(BOOST_ASIO_HAS_SECURE_RTL) Chris@16: int length = vsprintf(line, format, args); Chris@16: #endif // defined(BOOST_ASIO_HAS_SECURE_RTL) Chris@16: Chris@16: va_end(args); Chris@16: Chris@16: #if defined(BOOST_ASIO_WINDOWS) Chris@16: HANDLE stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE); Chris@16: DWORD bytes_written = 0; Chris@16: ::WriteFile(stderr_handle, line, length, &bytes_written, 0); Chris@16: #else // defined(BOOST_ASIO_WINDOWS) Chris@16: ::write(STDERR_FILENO, line, length); Chris@16: #endif // defined(BOOST_ASIO_WINDOWS) Chris@16: } Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace asio Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING) Chris@16: Chris@16: #endif // BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP