2#include <asyncpp/detail/concepts.h>
3#include <asyncpp/detail/parameter_pack.h>
8#ifndef ASYNCPP_DEFAULT_ALLOCATOR
9 using default_allocator_type = std::allocator<std::byte>;
11 using default_allocator_type = ASYNCPP_DEFAULT_ALLOCATOR;
15namespace asyncpp::detail {
16 template<ByteAllocator Allocator>
17 class promise_allocator_base {
19 using allocator_type = Allocator;
21 template<
typename... Args>
22 void*
operator new(
size_t size, Args&&... args) {
23 if constexpr (std::allocator_traits<allocator_type>::is_always_equal::value) {
24 allocator_type alloc{};
25 return std::allocator_traits<allocator_type>::allocate(alloc, size);
27 static_assert(
sizeof...(Args) > 0,
"using a statefull allocator but no allocator passed");
28 allocator_type alloc = parameter_pack::get_last(args...);
29 static_assert(std::is_convertible_v<std::remove_cvref_t<
decltype(alloc)>&, allocator_type> ||
30 std::is_constructible_v<allocator_type,
decltype(alloc)>,
31 "last argument is not of allocator type");
32 auto ptr = std::allocator_traits<allocator_type>::allocate(alloc, size +
sizeof(allocator_type));
33 auto aptr =
new (ptr) allocator_type{std::move(alloc)};
37 void operator delete(
void* ptr,
size_t size) {
38 if (ptr ==
nullptr)
return;
39 if constexpr (std::allocator_traits<allocator_type>::is_always_equal::value) {
40 allocator_type alloc{};
41 std::allocator_traits<allocator_type>::deallocate(alloc,
static_cast<std::byte*
>(ptr), size);
43 allocator_type* info =
static_cast<allocator_type*
>(ptr) - 1;
44 auto alloc = std::move(*info);
45 std::allocator_traits<allocator_type>::deallocate(
46 alloc,
static_cast<std::byte*
>(
static_cast<void*
>(info)), size +
sizeof(Allocator));
Provides a consistent import interface for coroutine, experimental/coroutine or a best effort fallbac...