Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

359 lines
9.8KB

  1. //
  2. // detail/impl/handler_tracking.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 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. #ifndef ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP
  11. #define ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #if defined(ASIO_CUSTOM_HANDLER_TRACKING)
  17. // The handler tracking implementation is provided by the user-specified header.
  18. #elif defined(ASIO_ENABLE_HANDLER_TRACKING)
  19. #include <cstdarg>
  20. #include <cstdio>
  21. #include "asio/detail/handler_tracking.hpp"
  22. #if defined(ASIO_HAS_BOOST_DATE_TIME)
  23. # include "asio/time_traits.hpp"
  24. #elif defined(ASIO_HAS_CHRONO)
  25. # include "asio/detail/chrono.hpp"
  26. # include "asio/detail/chrono_time_traits.hpp"
  27. # include "asio/wait_traits.hpp"
  28. #endif // defined(ASIO_HAS_BOOST_DATE_TIME)
  29. #if defined(ASIO_WINDOWS_RUNTIME)
  30. # include "asio/detail/socket_types.hpp"
  31. #elif !defined(ASIO_WINDOWS)
  32. # include <unistd.h>
  33. #endif // !defined(ASIO_WINDOWS)
  34. #include "asio/detail/push_options.hpp"
  35. namespace asio {
  36. namespace detail {
  37. struct handler_tracking_timestamp
  38. {
  39. uint64_t seconds;
  40. uint64_t microseconds;
  41. handler_tracking_timestamp()
  42. {
  43. #if defined(ASIO_HAS_BOOST_DATE_TIME)
  44. boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
  45. boost::posix_time::time_duration now =
  46. boost::posix_time::microsec_clock::universal_time() - epoch;
  47. #elif defined(ASIO_HAS_CHRONO)
  48. typedef chrono_time_traits<chrono::system_clock,
  49. asio::wait_traits<chrono::system_clock> > traits_helper;
  50. traits_helper::posix_time_duration now(
  51. chrono::system_clock::now().time_since_epoch());
  52. #endif
  53. seconds = static_cast<uint64_t>(now.total_seconds());
  54. microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000);
  55. }
  56. };
  57. struct handler_tracking::tracking_state
  58. {
  59. static_mutex mutex_;
  60. uint64_t next_id_;
  61. tss_ptr<completion>* current_completion_;
  62. };
  63. handler_tracking::tracking_state* handler_tracking::get_state()
  64. {
  65. static tracking_state state = { ASIO_STATIC_MUTEX_INIT, 1, 0 };
  66. return &state;
  67. }
  68. void handler_tracking::init()
  69. {
  70. static tracking_state* state = get_state();
  71. state->mutex_.init();
  72. static_mutex::scoped_lock lock(state->mutex_);
  73. if (state->current_completion_ == 0)
  74. state->current_completion_ = new tss_ptr<completion>;
  75. }
  76. void handler_tracking::creation(execution_context&,
  77. handler_tracking::tracked_handler& h,
  78. const char* object_type, void* object,
  79. uintmax_t /*native_handle*/, const char* op_name)
  80. {
  81. static tracking_state* state = get_state();
  82. static_mutex::scoped_lock lock(state->mutex_);
  83. h.id_ = state->next_id_++;
  84. lock.unlock();
  85. handler_tracking_timestamp timestamp;
  86. uint64_t current_id = 0;
  87. if (completion* current_completion = *state->current_completion_)
  88. current_id = current_completion->id_;
  89. write_line(
  90. #if defined(ASIO_WINDOWS)
  91. "@asio|%I64u.%06I64u|%I64u*%I64u|%.20s@%p.%.50s\n",
  92. #else // defined(ASIO_WINDOWS)
  93. "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n",
  94. #endif // defined(ASIO_WINDOWS)
  95. timestamp.seconds, timestamp.microseconds,
  96. current_id, h.id_, object_type, object, op_name);
  97. }
  98. handler_tracking::completion::completion(
  99. const handler_tracking::tracked_handler& h)
  100. : id_(h.id_),
  101. invoked_(false),
  102. next_(*get_state()->current_completion_)
  103. {
  104. *get_state()->current_completion_ = this;
  105. }
  106. handler_tracking::completion::~completion()
  107. {
  108. if (id_)
  109. {
  110. handler_tracking_timestamp timestamp;
  111. write_line(
  112. #if defined(ASIO_WINDOWS)
  113. "@asio|%I64u.%06I64u|%c%I64u|\n",
  114. #else // defined(ASIO_WINDOWS)
  115. "@asio|%llu.%06llu|%c%llu|\n",
  116. #endif // defined(ASIO_WINDOWS)
  117. timestamp.seconds, timestamp.microseconds,
  118. invoked_ ? '!' : '~', id_);
  119. }
  120. *get_state()->current_completion_ = next_;
  121. }
  122. void handler_tracking::completion::invocation_begin()
  123. {
  124. handler_tracking_timestamp timestamp;
  125. write_line(
  126. #if defined(ASIO_WINDOWS)
  127. "@asio|%I64u.%06I64u|>%I64u|\n",
  128. #else // defined(ASIO_WINDOWS)
  129. "@asio|%llu.%06llu|>%llu|\n",
  130. #endif // defined(ASIO_WINDOWS)
  131. timestamp.seconds, timestamp.microseconds, id_);
  132. invoked_ = true;
  133. }
  134. void handler_tracking::completion::invocation_begin(
  135. const asio::error_code& ec)
  136. {
  137. handler_tracking_timestamp timestamp;
  138. write_line(
  139. #if defined(ASIO_WINDOWS)
  140. "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d\n",
  141. #else // defined(ASIO_WINDOWS)
  142. "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n",
  143. #endif // defined(ASIO_WINDOWS)
  144. timestamp.seconds, timestamp.microseconds,
  145. id_, ec.category().name(), ec.value());
  146. invoked_ = true;
  147. }
  148. void handler_tracking::completion::invocation_begin(
  149. const asio::error_code& ec, std::size_t bytes_transferred)
  150. {
  151. handler_tracking_timestamp timestamp;
  152. write_line(
  153. #if defined(ASIO_WINDOWS)
  154. "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,bytes_transferred=%I64u\n",
  155. #else // defined(ASIO_WINDOWS)
  156. "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n",
  157. #endif // defined(ASIO_WINDOWS)
  158. timestamp.seconds, timestamp.microseconds,
  159. id_, ec.category().name(), ec.value(),
  160. static_cast<uint64_t>(bytes_transferred));
  161. invoked_ = true;
  162. }
  163. void handler_tracking::completion::invocation_begin(
  164. const asio::error_code& ec, int signal_number)
  165. {
  166. handler_tracking_timestamp timestamp;
  167. write_line(
  168. #if defined(ASIO_WINDOWS)
  169. "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,signal_number=%d\n",
  170. #else // defined(ASIO_WINDOWS)
  171. "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n",
  172. #endif // defined(ASIO_WINDOWS)
  173. timestamp.seconds, timestamp.microseconds,
  174. id_, ec.category().name(), ec.value(), signal_number);
  175. invoked_ = true;
  176. }
  177. void handler_tracking::completion::invocation_begin(
  178. const asio::error_code& ec, const char* arg)
  179. {
  180. handler_tracking_timestamp timestamp;
  181. write_line(
  182. #if defined(ASIO_WINDOWS)
  183. "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,%.50s\n",
  184. #else // defined(ASIO_WINDOWS)
  185. "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n",
  186. #endif // defined(ASIO_WINDOWS)
  187. timestamp.seconds, timestamp.microseconds,
  188. id_, ec.category().name(), ec.value(), arg);
  189. invoked_ = true;
  190. }
  191. void handler_tracking::completion::invocation_end()
  192. {
  193. if (id_)
  194. {
  195. handler_tracking_timestamp timestamp;
  196. write_line(
  197. #if defined(ASIO_WINDOWS)
  198. "@asio|%I64u.%06I64u|<%I64u|\n",
  199. #else // defined(ASIO_WINDOWS)
  200. "@asio|%llu.%06llu|<%llu|\n",
  201. #endif // defined(ASIO_WINDOWS)
  202. timestamp.seconds, timestamp.microseconds, id_);
  203. id_ = 0;
  204. }
  205. }
  206. void handler_tracking::operation(execution_context&,
  207. const char* object_type, void* object,
  208. uintmax_t /*native_handle*/, const char* op_name)
  209. {
  210. static tracking_state* state = get_state();
  211. handler_tracking_timestamp timestamp;
  212. unsigned long long current_id = 0;
  213. if (completion* current_completion = *state->current_completion_)
  214. current_id = current_completion->id_;
  215. write_line(
  216. #if defined(ASIO_WINDOWS)
  217. "@asio|%I64u.%06I64u|%I64u|%.20s@%p.%.50s\n",
  218. #else // defined(ASIO_WINDOWS)
  219. "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n",
  220. #endif // defined(ASIO_WINDOWS)
  221. timestamp.seconds, timestamp.microseconds,
  222. current_id, object_type, object, op_name);
  223. }
  224. void handler_tracking::reactor_registration(execution_context& /*context*/,
  225. uintmax_t /*native_handle*/, uintmax_t /*registration*/)
  226. {
  227. }
  228. void handler_tracking::reactor_deregistration(execution_context& /*context*/,
  229. uintmax_t /*native_handle*/, uintmax_t /*registration*/)
  230. {
  231. }
  232. void handler_tracking::reactor_events(execution_context& /*context*/,
  233. uintmax_t /*native_handle*/, unsigned /*events*/)
  234. {
  235. }
  236. void handler_tracking::reactor_operation(
  237. const tracked_handler& h, const char* op_name,
  238. const asio::error_code& ec)
  239. {
  240. handler_tracking_timestamp timestamp;
  241. write_line(
  242. #if defined(ASIO_WINDOWS)
  243. "@asio|%I64u.%06I64u|.%I64u|%s,ec=%.20s:%d\n",
  244. #else // defined(ASIO_WINDOWS)
  245. "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d\n",
  246. #endif // defined(ASIO_WINDOWS)
  247. timestamp.seconds, timestamp.microseconds,
  248. h.id_, op_name, ec.category().name(), ec.value());
  249. }
  250. void handler_tracking::reactor_operation(
  251. const tracked_handler& h, const char* op_name,
  252. const asio::error_code& ec, std::size_t bytes_transferred)
  253. {
  254. handler_tracking_timestamp timestamp;
  255. write_line(
  256. #if defined(ASIO_WINDOWS)
  257. "@asio|%I64u.%06I64u|.%I64u|%s,ec=%.20s:%d,bytes_transferred=%I64u\n",
  258. #else // defined(ASIO_WINDOWS)
  259. "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d,bytes_transferred=%llu\n",
  260. #endif // defined(ASIO_WINDOWS)
  261. timestamp.seconds, timestamp.microseconds,
  262. h.id_, op_name, ec.category().name(), ec.value(),
  263. static_cast<uint64_t>(bytes_transferred));
  264. }
  265. void handler_tracking::write_line(const char* format, ...)
  266. {
  267. using namespace std; // For sprintf (or equivalent).
  268. va_list args;
  269. va_start(args, format);
  270. char line[256] = "";
  271. #if defined(ASIO_HAS_SECURE_RTL)
  272. int length = vsprintf_s(line, sizeof(line), format, args);
  273. #else // defined(ASIO_HAS_SECURE_RTL)
  274. int length = vsprintf(line, format, args);
  275. #endif // defined(ASIO_HAS_SECURE_RTL)
  276. va_end(args);
  277. #if defined(ASIO_WINDOWS_RUNTIME)
  278. wchar_t wline[256] = L"";
  279. mbstowcs_s(0, wline, sizeof(wline) / sizeof(wchar_t), line, length);
  280. ::OutputDebugStringW(wline);
  281. #elif defined(ASIO_WINDOWS)
  282. HANDLE stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE);
  283. DWORD bytes_written = 0;
  284. ::WriteFile(stderr_handle, line, length, &bytes_written, 0);
  285. #else // defined(ASIO_WINDOWS)
  286. ::write(STDERR_FILENO, line, length);
  287. #endif // defined(ASIO_WINDOWS)
  288. }
  289. } // namespace detail
  290. } // namespace asio
  291. #include "asio/detail/pop_options.hpp"
  292. #endif // defined(ASIO_ENABLE_HANDLER_TRACKING)
  293. #endif // ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP