Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-28 08:11:34

0001 //
0002 // experimental/detail/coro_promise_allocator.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2021-2023 Klemens D. Morgenstern
0006 //                         (klemens dot morgenstern at gmx dot net)
0007 //
0008 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0009 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 <limits>
0017 #include <boost/asio/experimental/coro_traits.hpp>
0018 
0019 namespace boost {
0020 namespace asio {
0021 namespace experimental {
0022 namespace detail {
0023 
0024 /// Allocate the memory and put the allocator behind the coro memory
0025 template <typename AllocatorType>
0026 void* allocate_coroutine(const std::size_t size, AllocatorType alloc_)
0027 {
0028   using alloc_type = typename std::allocator_traits<AllocatorType>::template
0029     rebind_alloc<unsigned char>;
0030   alloc_type alloc{alloc_};
0031 
0032   const auto align_needed = size % alignof(alloc_type);
0033   const auto align_offset = align_needed != 0
0034     ? alignof(alloc_type) - align_needed : 0ull;
0035   const auto alloc_size = size + sizeof(alloc_type) + align_offset;
0036   const auto raw =
0037     std::allocator_traits<alloc_type>::allocate(alloc, alloc_size);
0038   new(raw + size + align_offset) alloc_type(std::move(alloc));
0039 
0040   return raw;
0041 }
0042 
0043 /// Deallocate the memory and destroy the allocator in the coro memory.
0044 template <typename AllocatorType>
0045 void deallocate_coroutine(void* raw_, const std::size_t size)
0046 {
0047   using alloc_type = typename std::allocator_traits<AllocatorType>::template
0048     rebind_alloc<unsigned char>;
0049 
0050   const auto raw = static_cast<unsigned char *>(raw_);
0051 
0052   const auto align_needed = size % alignof(alloc_type);
0053   const auto align_offset = align_needed != 0
0054     ? alignof(alloc_type) - align_needed : 0ull;
0055   const auto alloc_size = size + sizeof(alloc_type) + align_offset;
0056 
0057   auto alloc_p = reinterpret_cast<alloc_type *>(raw + size + align_offset);
0058   auto alloc = std::move(*alloc_p);
0059   alloc_p->~alloc_type();
0060   std::allocator_traits<alloc_type>::deallocate(alloc, raw, alloc_size);
0061 }
0062 
0063 template <typename T>
0064 constexpr std::size_t variadic_first(std::size_t = 0u)
0065 {
0066   return std::numeric_limits<std::size_t>::max();
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(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, 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 } // namespace detail
0139 } // namespace experimental
0140 } // namespace asio
0141 } // namespace boost
0142 
0143 #endif // BOOST_ASIO_EXPERIMENTAL_DETAIL_CORO_PROMISE_ALLOCATOR_HPP