| 1 | // |
| 2 | // detail/handler_alloc_helpers.hpp |
| 3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 4 | // |
| 5 | // Copyright (c) 2003-2024 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 BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP |
| 12 | #define BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP |
| 13 | |
| 14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
| 15 | # pragma once |
| 16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
| 17 | |
| 18 | #include <boost/asio/detail/config.hpp> |
| 19 | #include <boost/asio/detail/memory.hpp> |
| 20 | #include <boost/asio/detail/noncopyable.hpp> |
| 21 | #include <boost/asio/detail/recycling_allocator.hpp> |
| 22 | #include <boost/asio/detail/thread_info_base.hpp> |
| 23 | #include <boost/asio/associated_allocator.hpp> |
| 24 | |
| 25 | #include <boost/asio/detail/push_options.hpp> |
| 26 | |
| 27 | namespace boost { |
| 28 | namespace asio { |
| 29 | namespace detail { |
| 30 | |
| 31 | inline void* default_allocate(std::size_t s, |
| 32 | std::size_t align = BOOST_ASIO_DEFAULT_ALIGN) |
| 33 | { |
| 34 | #if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING) |
| 35 | return boost::asio::detail::thread_info_base::allocate( |
| 36 | this_thread: boost::asio::detail::thread_context::top_of_thread_call_stack(), |
| 37 | size: s, align); |
| 38 | #else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING) |
| 39 | return boost::asio::aligned_new(align, s); |
| 40 | #endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING) |
| 41 | } |
| 42 | |
| 43 | inline void default_deallocate(void* p, std::size_t s) |
| 44 | { |
| 45 | #if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING) |
| 46 | boost::asio::detail::thread_info_base::deallocate( |
| 47 | this_thread: boost::asio::detail::thread_context::top_of_thread_call_stack(), pointer: p, size: s); |
| 48 | #else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING) |
| 49 | (void)s; |
| 50 | boost::asio::aligned_delete(p); |
| 51 | #endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING) |
| 52 | } |
| 53 | |
| 54 | template <typename T> |
| 55 | class default_allocator |
| 56 | { |
| 57 | public: |
| 58 | typedef T value_type; |
| 59 | |
| 60 | template <typename U> |
| 61 | struct rebind |
| 62 | { |
| 63 | typedef default_allocator<U> other; |
| 64 | }; |
| 65 | |
| 66 | default_allocator() noexcept |
| 67 | { |
| 68 | } |
| 69 | |
| 70 | template <typename U> |
| 71 | default_allocator(const default_allocator<U>&) noexcept |
| 72 | { |
| 73 | } |
| 74 | |
| 75 | T* allocate(std::size_t n) |
| 76 | { |
| 77 | return static_cast<T*>(default_allocate(s: sizeof(T) * n, align: alignof(T))); |
| 78 | } |
| 79 | |
| 80 | void deallocate(T* p, std::size_t n) |
| 81 | { |
| 82 | default_deallocate(p, sizeof(T) * n); |
| 83 | } |
| 84 | }; |
| 85 | |
| 86 | template <> |
| 87 | class default_allocator<void> |
| 88 | { |
| 89 | public: |
| 90 | typedef void value_type; |
| 91 | |
| 92 | template <typename U> |
| 93 | struct rebind |
| 94 | { |
| 95 | typedef default_allocator<U> other; |
| 96 | }; |
| 97 | |
| 98 | default_allocator() noexcept |
| 99 | { |
| 100 | } |
| 101 | |
| 102 | template <typename U> |
| 103 | default_allocator(const default_allocator<U>&) noexcept |
| 104 | { |
| 105 | } |
| 106 | }; |
| 107 | |
| 108 | template <typename Allocator> |
| 109 | struct get_default_allocator |
| 110 | { |
| 111 | typedef Allocator type; |
| 112 | |
| 113 | static type get(const Allocator& a) |
| 114 | { |
| 115 | return a; |
| 116 | } |
| 117 | }; |
| 118 | |
| 119 | template <typename T> |
| 120 | struct get_default_allocator<std::allocator<T>> |
| 121 | { |
| 122 | typedef default_allocator<T> type; |
| 123 | |
| 124 | static type get(const std::allocator<T>&) |
| 125 | { |
| 126 | return type(); |
| 127 | } |
| 128 | }; |
| 129 | |
| 130 | } // namespace detail |
| 131 | } // namespace asio |
| 132 | } // namespace boost |
| 133 | |
| 134 | #define BOOST_ASIO_DEFINE_HANDLER_PTR(op) \ |
| 135 | struct ptr \ |
| 136 | { \ |
| 137 | Handler* h; \ |
| 138 | op* v; \ |
| 139 | op* p; \ |
| 140 | ~ptr() \ |
| 141 | { \ |
| 142 | reset(); \ |
| 143 | } \ |
| 144 | static op* allocate(Handler& handler) \ |
| 145 | { \ |
| 146 | typedef typename ::boost::asio::associated_allocator< \ |
| 147 | Handler>::type associated_allocator_type; \ |
| 148 | typedef typename ::boost::asio::detail::get_default_allocator< \ |
| 149 | associated_allocator_type>::type default_allocator_type; \ |
| 150 | BOOST_ASIO_REBIND_ALLOC(default_allocator_type, op) a( \ |
| 151 | ::boost::asio::detail::get_default_allocator< \ |
| 152 | associated_allocator_type>::get( \ |
| 153 | ::boost::asio::get_associated_allocator(handler))); \ |
| 154 | return a.allocate(1); \ |
| 155 | } \ |
| 156 | void reset() \ |
| 157 | { \ |
| 158 | if (p) \ |
| 159 | { \ |
| 160 | p->~op(); \ |
| 161 | p = 0; \ |
| 162 | } \ |
| 163 | if (v) \ |
| 164 | { \ |
| 165 | typedef typename ::boost::asio::associated_allocator< \ |
| 166 | Handler>::type associated_allocator_type; \ |
| 167 | typedef typename ::boost::asio::detail::get_default_allocator< \ |
| 168 | associated_allocator_type>::type default_allocator_type; \ |
| 169 | BOOST_ASIO_REBIND_ALLOC(default_allocator_type, op) a( \ |
| 170 | ::boost::asio::detail::get_default_allocator< \ |
| 171 | associated_allocator_type>::get( \ |
| 172 | ::boost::asio::get_associated_allocator(*h))); \ |
| 173 | a.deallocate(static_cast<op*>(v), 1); \ |
| 174 | v = 0; \ |
| 175 | } \ |
| 176 | } \ |
| 177 | } \ |
| 178 | /**/ |
| 179 | |
| 180 | #define BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(purpose, op) \ |
| 181 | struct ptr \ |
| 182 | { \ |
| 183 | const Alloc* a; \ |
| 184 | void* v; \ |
| 185 | op* p; \ |
| 186 | ~ptr() \ |
| 187 | { \ |
| 188 | reset(); \ |
| 189 | } \ |
| 190 | static op* allocate(const Alloc& a) \ |
| 191 | { \ |
| 192 | typedef typename ::boost::asio::detail::get_recycling_allocator< \ |
| 193 | Alloc, purpose>::type recycling_allocator_type; \ |
| 194 | BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \ |
| 195 | ::boost::asio::detail::get_recycling_allocator< \ |
| 196 | Alloc, purpose>::get(a)); \ |
| 197 | return a1.allocate(1); \ |
| 198 | } \ |
| 199 | void reset() \ |
| 200 | { \ |
| 201 | if (p) \ |
| 202 | { \ |
| 203 | p->~op(); \ |
| 204 | p = 0; \ |
| 205 | } \ |
| 206 | if (v) \ |
| 207 | { \ |
| 208 | typedef typename ::boost::asio::detail::get_recycling_allocator< \ |
| 209 | Alloc, purpose>::type recycling_allocator_type; \ |
| 210 | BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \ |
| 211 | ::boost::asio::detail::get_recycling_allocator< \ |
| 212 | Alloc, purpose>::get(*a)); \ |
| 213 | a1.deallocate(static_cast<op*>(v), 1); \ |
| 214 | v = 0; \ |
| 215 | } \ |
| 216 | } \ |
| 217 | } \ |
| 218 | /**/ |
| 219 | |
| 220 | #define BOOST_ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \ |
| 221 | BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR( \ |
| 222 | ::boost::asio::detail::thread_info_base::default_tag, op ) \ |
| 223 | /**/ |
| 224 | |
| 225 | #include <boost/asio/detail/pop_options.hpp> |
| 226 | |
| 227 | #endif // BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP |
| 228 | |