1 // 2 // detail/impl/handler_tracking.ipp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP 12 #define ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP 13 14 15 #include "asio/detail/config.hpp" 16 17 #if defined(ASIO_ENABLE_HANDLER_TRACKING) 18 19 #include <cstdarg> 20 #include <cstdio> 21 #include "asio/detail/handler_tracking.hpp" 22 23 # include <chrono> 24 # include "asio/detail/chrono_time_traits.hpp" 25 # include "asio/wait_traits.hpp" 26 27 # include <unistd.h> 28 29 #include "asio/detail/push_options.hpp" 30 31 namespace asio { 32 namespace detail { 33 34 struct handler_tracking_timestamp 35 { 36 uint64_t seconds; 37 uint64_t microseconds; 38 39 handler_tracking_timestamp() 40 { 41 typedef chrono_time_traits<std::chrono::system_clock, 42 asio::wait_traits<std::chrono::system_clock> > traits_helper; 43 traits_helper::posix_time_duration now( 44 std::chrono::system_clock::now().time_since_epoch()); 45 seconds = static_cast<uint64_t>(now.total_seconds()); 46 microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000); 47 } 48 }; 49 50 struct handler_tracking::tracking_state 51 { 52 static_mutex mutex_; 53 uint64_t next_id_; 54 tss_ptr<completion>* current_completion_; 55 }; 56 57 handler_tracking::tracking_state* handler_tracking::get_state() 58 { 59 static tracking_state state = { ASIO_STATIC_MUTEX_INIT, 1, 0 }; 60 return &state; 61 } 62 63 void handler_tracking::init() 64 { 65 static tracking_state* state = get_state(); 66 67 state->mutex_.init(); 68 69 static_mutex::scoped_lock lock(state->mutex_); 70 if (state->current_completion_ == 0) 71 state->current_completion_ = new tss_ptr<completion>; 72 } 73 74 void handler_tracking::creation(handler_tracking::tracked_handler* h, 75 const char* object_type, void* object, const char* op_name) 76 { 77 static tracking_state* state = get_state(); 78 79 static_mutex::scoped_lock lock(state->mutex_); 80 h->id_ = state->next_id_++; 81 lock.unlock(); 82 83 handler_tracking_timestamp timestamp; 84 85 uint64_t current_id = 0; 86 if (completion* current_completion = *state->current_completion_) 87 current_id = current_completion->id_; 88 89 write_line( 90 "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n", 91 timestamp.seconds, timestamp.microseconds, 92 current_id, h->id_, object_type, object, op_name); 93 } 94 95 handler_tracking::completion::completion(handler_tracking::tracked_handler* h) 96 : id_(h->id_), 97 invoked_(false), 98 next_(*get_state()->current_completion_) 99 { 100 *get_state()->current_completion_ = this; 101 } 102 103 handler_tracking::completion::~completion() 104 { 105 if (id_) 106 { 107 handler_tracking_timestamp timestamp; 108 109 write_line( 110 "@asio|%llu.%06llu|%c%llu|\n", 111 timestamp.seconds, timestamp.microseconds, 112 invoked_ ? '!' : '~', id_); 113 } 114 115 *get_state()->current_completion_ = next_; 116 } 117 118 void handler_tracking::completion::invocation_begin() 119 { 120 handler_tracking_timestamp timestamp; 121 122 write_line( 123 "@asio|%llu.%06llu|>%llu|\n", 124 timestamp.seconds, timestamp.microseconds, id_); 125 126 invoked_ = true; 127 } 128 129 void handler_tracking::completion::invocation_begin( 130 const asio::error_code& ec) 131 { 132 handler_tracking_timestamp timestamp; 133 134 write_line( 135 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n", 136 timestamp.seconds, timestamp.microseconds, 137 id_, ec.category().name(), ec.value()); 138 139 invoked_ = true; 140 } 141 142 void handler_tracking::completion::invocation_begin( 143 const asio::error_code& ec, std::size_t bytes_transferred) 144 { 145 handler_tracking_timestamp timestamp; 146 147 write_line( 148 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n", 149 timestamp.seconds, timestamp.microseconds, 150 id_, ec.category().name(), ec.value(), 151 static_cast<uint64_t>(bytes_transferred)); 152 153 invoked_ = true; 154 } 155 156 void handler_tracking::completion::invocation_begin( 157 const asio::error_code& ec, int signal_number) 158 { 159 handler_tracking_timestamp timestamp; 160 161 write_line( 162 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n", 163 timestamp.seconds, timestamp.microseconds, 164 id_, ec.category().name(), ec.value(), signal_number); 165 166 invoked_ = true; 167 } 168 169 void handler_tracking::completion::invocation_begin( 170 const asio::error_code& ec, const char* arg) 171 { 172 handler_tracking_timestamp timestamp; 173 174 write_line( 175 "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n", 176 timestamp.seconds, timestamp.microseconds, 177 id_, ec.category().name(), ec.value(), arg); 178 179 invoked_ = true; 180 } 181 182 void handler_tracking::completion::invocation_end() 183 { 184 if (id_) 185 { 186 handler_tracking_timestamp timestamp; 187 188 write_line( 189 "@asio|%llu.%06llu|<%llu|\n", 190 timestamp.seconds, timestamp.microseconds, id_); 191 192 id_ = 0; 193 } 194 } 195 196 void handler_tracking::operation(const char* object_type, 197 void* object, const char* op_name) 198 { 199 static tracking_state* state = get_state(); 200 201 handler_tracking_timestamp timestamp; 202 203 unsigned long long current_id = 0; 204 if (completion* current_completion = *state->current_completion_) 205 current_id = current_completion->id_; 206 207 write_line( 208 "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n", 209 timestamp.seconds, timestamp.microseconds, 210 current_id, object_type, object, op_name); 211 } 212 213 void handler_tracking::write_line(const char* format, ...) 214 { 215 using namespace std; // For sprintf (or equivalent). 216 217 va_list args; 218 va_start(args, format); 219 220 char line[256] = ""; 221 #if defined(ASIO_HAS_SECURE_RTL) 222 int length = vsprintf_s(line, sizeof(line), format, args); 223 #else // defined(ASIO_HAS_SECURE_RTL) 224 int length = vsprintf(line, format, args); 225 #endif // defined(ASIO_HAS_SECURE_RTL) 226 227 va_end(args); 228 229 ::write(STDERR_FILENO, line, length); 230 } 231 232 } // namespace detail 233 } // namespace asio 234 235 #include "asio/detail/pop_options.hpp" 236 237 #endif // defined(ASIO_ENABLE_HANDLER_TRACKING) 238 239 #endif // ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP 240