thread_info_base.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. //
  2. // detail/thread_info_base.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2021 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 BOOST_ASIO_DETAIL_THREAD_INFO_BASE_HPP
  11. #define BOOST_ASIO_DETAIL_THREAD_INFO_BASE_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <climits>
  17. #include <cstddef>
  18. #include <boost/asio/detail/noncopyable.hpp>
  19. #if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) \
  20. && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  21. # include <exception>
  22. # include <boost/asio/multiple_exceptions.hpp>
  23. #endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
  24. // && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  25. #include <boost/asio/detail/push_options.hpp>
  26. namespace boost {
  27. namespace asio {
  28. namespace detail {
  29. class thread_info_base
  30. : private noncopyable
  31. {
  32. public:
  33. struct default_tag
  34. {
  35. enum { mem_index = 0 };
  36. };
  37. struct awaitable_frame_tag
  38. {
  39. enum { mem_index = 1 };
  40. };
  41. struct executor_function_tag
  42. {
  43. enum { mem_index = 2 };
  44. };
  45. thread_info_base()
  46. #if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) \
  47. && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  48. : has_pending_exception_(0)
  49. #endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
  50. // && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  51. {
  52. for (int i = 0; i < max_mem_index; ++i)
  53. reusable_memory_[i] = 0;
  54. }
  55. ~thread_info_base()
  56. {
  57. for (int i = 0; i < max_mem_index; ++i)
  58. {
  59. // The following test for non-null pointers is technically redundant, but
  60. // it is significantly faster when using a tight io_context::poll() loop
  61. // in latency sensitive applications.
  62. if (reusable_memory_[i])
  63. ::operator delete(reusable_memory_[i]);
  64. }
  65. }
  66. static void* allocate(thread_info_base* this_thread, std::size_t size)
  67. {
  68. return allocate(default_tag(), this_thread, size);
  69. }
  70. static void deallocate(thread_info_base* this_thread,
  71. void* pointer, std::size_t size)
  72. {
  73. deallocate(default_tag(), this_thread, pointer, size);
  74. }
  75. template <typename Purpose>
  76. static void* allocate(Purpose, thread_info_base* this_thread,
  77. std::size_t size)
  78. {
  79. std::size_t chunks = (size + chunk_size - 1) / chunk_size;
  80. if (this_thread && this_thread->reusable_memory_[Purpose::mem_index])
  81. {
  82. void* const pointer = this_thread->reusable_memory_[Purpose::mem_index];
  83. this_thread->reusable_memory_[Purpose::mem_index] = 0;
  84. unsigned char* const mem = static_cast<unsigned char*>(pointer);
  85. if (static_cast<std::size_t>(mem[0]) >= chunks)
  86. {
  87. mem[size] = mem[0];
  88. return pointer;
  89. }
  90. ::operator delete(pointer);
  91. }
  92. void* const pointer = ::operator new(chunks * chunk_size + 1);
  93. unsigned char* const mem = static_cast<unsigned char*>(pointer);
  94. mem[size] = (chunks <= UCHAR_MAX) ? static_cast<unsigned char>(chunks) : 0;
  95. return pointer;
  96. }
  97. template <typename Purpose>
  98. static void deallocate(Purpose, thread_info_base* this_thread,
  99. void* pointer, std::size_t size)
  100. {
  101. if (size <= chunk_size * UCHAR_MAX)
  102. {
  103. if (this_thread && this_thread->reusable_memory_[Purpose::mem_index] == 0)
  104. {
  105. unsigned char* const mem = static_cast<unsigned char*>(pointer);
  106. mem[0] = mem[size];
  107. this_thread->reusable_memory_[Purpose::mem_index] = pointer;
  108. return;
  109. }
  110. }
  111. ::operator delete(pointer);
  112. }
  113. void capture_current_exception()
  114. {
  115. #if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) \
  116. && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  117. switch (has_pending_exception_)
  118. {
  119. case 0:
  120. has_pending_exception_ = 1;
  121. pending_exception_ = std::current_exception();
  122. break;
  123. case 1:
  124. has_pending_exception_ = 2;
  125. pending_exception_ =
  126. std::make_exception_ptr<multiple_exceptions>(
  127. multiple_exceptions(pending_exception_));
  128. break;
  129. default:
  130. break;
  131. }
  132. #endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
  133. // && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  134. }
  135. void rethrow_pending_exception()
  136. {
  137. #if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) \
  138. && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  139. if (has_pending_exception_ > 0)
  140. {
  141. has_pending_exception_ = 0;
  142. std::exception_ptr ex(
  143. BOOST_ASIO_MOVE_CAST(std::exception_ptr)(
  144. pending_exception_));
  145. std::rethrow_exception(ex);
  146. }
  147. #endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
  148. // && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  149. }
  150. private:
  151. enum { chunk_size = 4 };
  152. enum { max_mem_index = 3 };
  153. void* reusable_memory_[max_mem_index];
  154. #if defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR) \
  155. && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  156. int has_pending_exception_;
  157. std::exception_ptr pending_exception_;
  158. #endif // defined(BOOST_ASIO_HAS_STD_EXCEPTION_PTR)
  159. // && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  160. };
  161. } // namespace detail
  162. } // namespace asio
  163. } // namespace boost
  164. #include <boost/asio/detail/pop_options.hpp>
  165. #endif // BOOST_ASIO_DETAIL_THREAD_INFO_BASE_HPP