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