File indexing completed on 2025-01-18 09:28:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_ASIO_EXPERIMENTAL_DETAIL_CORO_PROMISE_ALLOCATOR_HPP
0013 #define BOOST_ASIO_EXPERIMENTAL_DETAIL_CORO_PROMISE_ALLOCATOR_HPP
0014
0015 #include <boost/asio/detail/config.hpp>
0016 #include <boost/asio/experimental/coro_traits.hpp>
0017
0018 namespace boost {
0019 namespace asio {
0020 namespace experimental {
0021 namespace detail {
0022
0023
0024 template <typename AllocatorType>
0025 void* allocate_coroutine(const std::size_t size, AllocatorType alloc_)
0026 {
0027 using alloc_type = typename std::allocator_traits<AllocatorType>::template
0028 rebind_alloc<unsigned char>;
0029 alloc_type alloc{alloc_};
0030
0031 const auto align_needed = size % alignof(alloc_type);
0032 const auto align_offset = align_needed != 0
0033 ? alignof(alloc_type) - align_needed : 0ull;
0034 const auto alloc_size = size + sizeof(alloc_type) + align_offset;
0035 const auto raw =
0036 std::allocator_traits<alloc_type>::allocate(alloc, alloc_size);
0037 new(raw + size + align_offset) alloc_type(std::move(alloc));
0038
0039 return raw;
0040 }
0041
0042
0043 template <typename AllocatorType>
0044 void deallocate_coroutine(void* raw_, const std::size_t size)
0045 {
0046 using alloc_type = typename std::allocator_traits<AllocatorType>::template
0047 rebind_alloc<unsigned char>;
0048
0049 const auto raw = static_cast<unsigned char *>(raw_);
0050
0051 const auto align_needed = size % alignof(alloc_type);
0052 const auto align_offset = align_needed != 0
0053 ? alignof(alloc_type) - align_needed : 0ull;
0054 const auto alloc_size = size + sizeof(alloc_type) + align_offset;
0055
0056 auto alloc_p = reinterpret_cast<alloc_type *>(raw + size + align_offset);
0057 auto alloc = std::move(*alloc_p);
0058 alloc_p->~alloc_type();
0059 std::allocator_traits<alloc_type>::deallocate(alloc, raw, alloc_size);
0060 }
0061
0062 template <typename T>
0063 constexpr std::size_t variadic_first(std::size_t = 0u)
0064 {
0065 return std::numeric_limits<std::size_t>::max();
0066 }
0067
0068
0069 template <typename T, typename First, typename... Args>
0070 constexpr std::size_t variadic_first(std::size_t pos = 0u)
0071 {
0072 if constexpr (std::is_same_v<std::decay_t<First>, T>)
0073 return pos;
0074 else
0075 return variadic_first<T, Args...>(pos+1);
0076 }
0077
0078 template <std::size_t Idx, typename First, typename... Args>
0079 requires (Idx <= sizeof...(Args))
0080 constexpr decltype(auto) get_variadic(First&& first, Args&&... args)
0081 {
0082 if constexpr (Idx == 0u)
0083 return static_cast<First>(first);
0084 else
0085 return get_variadic<Idx-1u>(static_cast<Args>(args)...);
0086 }
0087
0088 template <std::size_t Idx>
0089 constexpr decltype(auto) get_variadic();
0090
0091 template <typename Allocator>
0092 struct coro_promise_allocator
0093 {
0094 using allocator_type = Allocator;
0095 allocator_type get_allocator() const {return alloc_;}
0096
0097 template <typename... Args>
0098 void* operator new(const std::size_t size, Args & ... args)
0099 {
0100 return allocate_coroutine(size,
0101 get_variadic<variadic_first<std::allocator_arg_t,
0102 std::decay_t<Args>...>() + 1u>(args...));
0103 }
0104
0105 void operator delete(void* raw, const std::size_t size)
0106 {
0107 deallocate_coroutine<allocator_type>(raw, size);
0108 }
0109
0110 template <typename... Args>
0111 coro_promise_allocator(Args&& ... args)
0112 : alloc_(
0113 get_variadic<variadic_first<std::allocator_arg_t,
0114 std::decay_t<Args>...>() + 1u>(args...))
0115 {
0116 }
0117
0118 private:
0119 allocator_type alloc_;
0120 };
0121
0122 template <>
0123 struct coro_promise_allocator<std::allocator<void>>
0124 {
0125 using allocator_type = std::allocator<void>;
0126
0127 template <typename... Args>
0128 coro_promise_allocator(Args&&...)
0129 {
0130 }
0131
0132 allocator_type get_allocator() const
0133 {
0134 return {};
0135 }
0136 };
0137
0138 }
0139 }
0140 }
0141 }
0142
0143 #endif