11#pragma once
22
33#include < atomic>
4+ #include < bit>
45#include < memory_resource>
56#include < cassert>
67#include < utility>
@@ -63,7 +64,7 @@ struct chunk_from {
6364 return std::assume_aligned<dd::coroframe_align ()>(resource ().allocate (sz));
6465 }
6566
66- void deallocate (void * p, std:: size_t sz) noexcept {
67+ void deallocate (void * p, size_t sz) noexcept {
6768 resource ().deallocate (p, sz);
6869 }
6970};
@@ -74,7 +75,7 @@ struct new_delete_resource {
7475 // not malloc because of memory alignment requirement
7576 return new char [sz];
7677 }
77- static void deallocate (void * p, std:: size_t ) noexcept {
78+ static void deallocate (void * p, size_t ) noexcept {
7879 delete[] static_cast <char *>(p);
7980 }
8081};
@@ -120,7 +121,7 @@ struct polymorphic_resource {
120121 void * allocate (size_t sz) {
121122 return passed->allocate (sz, coroframe_align ());
122123 }
123- void deallocate (void * p, std:: size_t sz) noexcept {
124+ void deallocate (void * p, size_t sz) noexcept {
124125 passed->deallocate (p, sz, coroframe_align ());
125126 }
126127};
@@ -176,6 +177,19 @@ constexpr size_t padding_len(size_t sz) noexcept {
176177 return (P - sz % P) % P;
177178}
178179
180+ template <size_t ALIGN>
181+ constexpr size_t aligned (size_t size) {
182+ if constexpr (ALIGN < 2 )
183+ return size;
184+ // is power of 2
185+ if constexpr (std::has_single_bit (ALIGN) == 1 ) {
186+ constexpr size_t mask = ALIGN - 1 ;
187+ return (size + mask) & ~mask;
188+ } else {
189+ return size + (ALIGN - size % ALIGN) % ALIGN;
190+ }
191+ }
192+
179193} // namespace noexport
180194
181195// inheritor(coroutine promise) may be allocated with 'R'
@@ -187,7 +201,7 @@ struct overload_new_delete {
187201 if constexpr (std::is_empty_v<R>)
188202 return (void *)r.allocate (frame_sz);
189203 else {
190- frame_sz + = noexport::padding_len <alignof (R)>(frame_sz);
204+ frame_sz = noexport::aligned <alignof (R)>(frame_sz);
191205 std::byte* p = (std::byte*)r.allocate (frame_sz + sizeof (R));
192206 new (p + frame_sz) R (std::move (r));
193207 return p;
@@ -204,20 +218,20 @@ struct overload_new_delete {
204218
205219 template <typename ... Args>
206220 requires (last_is_memory_resource_tag<Args...> && std::is_same_v<R, resource_type_t <Args...>>)
207- static void * operator new (std:: size_t frame_sz, Args&&... args) {
221+ static void * operator new (size_t frame_sz, Args&&... args) {
208222 static_assert (std::is_same_v<std::remove_cvref_t <noexport::last_type_t <Args...>>, with_resource<R>>);
209223 // old-style
210224 // return do_allocate(frame_sz, (args...[sizeof...(Args) - 1]).resource);
211225 auto voidify = [](auto & x) { return const_cast <void *>((const void volatile *)std::addressof (x)); };
212226 void * p = (voidify (args), ...);
213227 return do_allocate (frame_sz, static_cast <with_resource<R>*>(p)->resource );
214228 }
215- static void operator delete (void * ptr, std:: size_t frame_sz) noexcept {
229+ static void operator delete (void * ptr, size_t frame_sz) noexcept {
216230 if constexpr (std::is_empty_v<R>) {
217231 R r{};
218232 r.deallocate (ptr, frame_sz);
219233 } else {
220- frame_sz + = noexport::padding_len <alignof (R)>(frame_sz);
234+ frame_sz = noexport::aligned <alignof (R)>(frame_sz);
221235 R* onframe_resource = (R*)((std::byte*)ptr + frame_sz);
222236 assert ((((uintptr_t )onframe_resource % alignof (R)) == 0 ));
223237 if constexpr (std::is_trivially_destructible_v<R>) {
0 commit comments