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