25 concept coro_allocator_global = requires(std::size_t sz,
void *ptr) {
26 {T::alloc(sz)} -> std::same_as<void *>;
27 {T::dealloc(ptr, sz)}->std::same_as<
void>;
31 concept coro_allocator_local = (!coro_allocator_global<T> && requires(T a, std::size_t sz,
void *ptr) {
32 {a.alloc(sz)} -> std::same_as<void *>;
33 {T::dealloc(ptr, sz)}->std::same_as<
void>;
38 concept coro_allocator = std::same_as<T, std_allocator> || std::same_as<T, const std_allocator>
39 || coro_allocator_local<T> || coro_allocator_global<T>;
56 void *alloc(std::size_t size) {
59 ptr =
operator new(sz = size);
64 static void dealloc(
void *, std::size_t) {}
71 static_assert(coro_allocator<reusable_allocator>);
72 static_assert(coro_allocator<std_allocator>);
76 template<coro_allocator Alloc>
82 #ifdef LIBCORO_ENABLE_TRACE
83 void *
operator new(std::size_t sz) {
84 void *ptr = ::operator
new(sz);
88 void operator delete(
void *ptr, std::size_t sz) {
90 ::operator
delete(ptr);
96 class coro_allocator_helper<const std_allocator>:
public coro_allocator_helper<std_allocator> {
102 template<coro_allocator_local Alloc>
103 class coro_allocator_helper<Alloc> {
107 void operator delete(
void *ptr, std::size_t sz) {
109 Alloc::dealloc(ptr, sz);
112 template<
typename ... Args>
113 void *
operator new(std::size_t sz, Alloc &a, Args && ...) {
114 void *ptr = a.alloc(sz);
119 template<
typename ... Args>
120 void operator delete(
void *, Alloc &, Args && ...) {
121 throw std::logic_error(
"unreachable");
125 template<
typename This,
typename ... Args>
126 void *
operator new(std::size_t sz, This &, Alloc &a, Args && ...) {
127 void *ptr = a.alloc(sz);
132 template<
typename This,
typename ... Args>
133 void operator delete(
void *, This &, Alloc &, Args && ...) {
134 throw std::logic_error(
"unreachable");
142 void *
operator new(std::size_t sz);
148 template<coro_allocator_global Alloc>
149 class coro_allocator_helper<Alloc> {
151 void operator delete(
void *ptr, std::size_t sz) {
153 Alloc::dealloc(ptr, sz);
156 void *
operator new(std::size_t sz) {
157 void *ptr = Alloc::alloc(sz);;
164 concept memory_resource_pointer = requires(T x, std::size_t sz,
void *ptr) {
165 {x->allocate(sz)} ->std::same_as<
void *>;
166 {x->deallocate(ptr,sz)} ->std::same_as<
void>;
167 requires std::copy_constructible<T>;
188 template<memory_resource_po
inter Res>
191 template<std::convertible_to<Res> T>
192 pmr_allocator(T &&resource):_memory_resource(std::forward<Res>(resource)) {}
194 void *alloc(std::size_t sz) {
195 auto needsz = sz +
sizeof(Res);
196 void *ptr = _memory_resource->allocate(needsz);
197 Res *resptr =
reinterpret_cast<Res *
>(
reinterpret_cast<char *
>(ptr)+sz);
198 std::construct_at(resptr, _memory_resource);
202 static void dealloc(
void *ptr, std::size_t sz) {
203 auto needsz = sz +
sizeof(Res);
204 Res *resptr =
reinterpret_cast<Res *
>(
reinterpret_cast<char *
>(ptr)+sz);
205 Res memory_res ( std::move(*resptr));
206 std::destroy_at(resptr);
207 memory_res->deallocate(ptr, needsz);
211 Res _memory_resource;
inherit this class to include coro_allocator into your promise_type
Creates libcoro compatible allocator which uses an instance of std::pmr::memory_resource for allocati...
Handles allocation of single coroutine, if it is repeatedly allocated and deallocated.
represents standard allocator for coroutines
constexpr std_allocator standard_allocator
Global instance for std_allocator which can be used anywhere the allocator is requested.
void on_create(const void *, std::size_t)
Record creation of an coroutine.
void on_destroy(const void *, std::size_t)
Record destruction of an coroutine.