• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
31namespace asio {
32namespace detail {
33
34struct 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
50struct handler_tracking::tracking_state
51{
52  static_mutex mutex_;
53  uint64_t next_id_;
54  tss_ptr<completion>* current_completion_;
55};
56
57handler_tracking::tracking_state* handler_tracking::get_state()
58{
59  static tracking_state state = { ASIO_STATIC_MUTEX_INIT, 1, 0 };
60  return &state;
61}
62
63void 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
74void 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
95handler_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
103handler_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
118void 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
129void 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
142void 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
156void 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
169void 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
182void 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
196void 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
213void 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