48 template<class U, std::enable_if_t<std::is_convertible_v<U*, T*>,
int> = 0>
51 constexpr void operator()(T* ptr)
const noexcept(
noexcept(ptr->~T())) { ptr->~T(); }
54 template<
class T>
using Ptr = std::unique_ptr<T, Deleter<T>>;
55 using State = std::pair<size_t, size_t>;
61 : page_size_(page_size) {
62 pages_.emplace_back(Page{});
82 template<
class T,
class... Args>
constexpr Ptr<T> mk(Args&&... args) {
92 [[nodiscard]]
constexpr void*
allocate(
size_t num_bytes,
size_t align) {
93 if (num_bytes == 0)
return nullptr;
95 if (index_ + num_bytes > pages_.back().size) {
96 pages_.emplace_back(std::max(page_size_, num_bytes),
align);
102 auto result = pages_.back().buffer + index_;
107 template<
class T> [[nodiscard]]
constexpr T*
allocate(
size_t num_elems) {
108 return static_cast<T*
>(
allocate(num_elems * std::max(
sizeof(T),
alignof(T)),
alignof(T)));
124 constexpr void deallocate(
size_t num_bytes)
noexcept { index_ -= num_bytes; }
125 State state() const noexcept {
return {pages_.size(), index_}; }
128 if (
state.first == pages_.size())
129 index_ =
state.second;
138 swap(a1.pages_, a2.pages_);
139 swap(a1.page_size_, a2.page_size_);
140 swap(a1.index_, a2.index_);
145 static constexpr size_t align(
size_t i,
size_t a)
noexcept {
return (i + (a - 1)) & ~(a - 1); }
148 constexpr Arena&
align(
size_t a)
noexcept {
return index_ =
align(index_, a), *
this; }
151 constexpr Page() noexcept = default;
152 Page(
size_t size,
size_t align)
155 , buffer((
char*)::operator new[](size, std::align_val_t(align))) {}
156 constexpr ~Page() noexcept {
157 if (buffer) ::operator
delete[](buffer, std::align_val_t(align));
160 const size_t size = 0;
161 const size_t align = 0;
162 char* buffer =
nullptr;
165 std::list<Page> pages_;
An arena pre-allocates so-called pages of size Arena::page_size_.
constexpr void deallocate(size_t num_bytes) noexcept
Removes num_bytes again.
void deallocate(State state) noexcept
Arena(const Arena &)=delete
Arena(Arena &&other) noexcept
constexpr void * allocate(size_t num_bytes, size_t align)
Get n bytes of fresh memory.
static constexpr size_t align(size_t i, size_t a) noexcept
Align i to a.
std::pair< size_t, size_t > State
Arena(size_t page_size=Default_Page_Size)
friend void swap(Arena &a1, Arena &a2) noexcept
Arena & operator=(Arena)=delete
std::unique_ptr< T, Deleter< T > > Ptr
constexpr T * allocate(size_t num_elems)
constexpr Ptr< T > mk(Args &&... args)
This is a std::unique_ptr that uses the Arena under the hood and whose Deleter will only invoke the d...
constexpr Allocator< T > allocator() noexcept
Create Allocator from Arena.
static constexpr size_t Default_Page_Size
1MB.
State state() const noexcept
An allocator in order to use this Arena for containers.
constexpr bool operator!=(const Allocator< U > &a) const noexcept
constexpr T * allocate(size_t num_elems)
constexpr bool operator==(const Allocator< U > &a) const noexcept
constexpr void deallocate(T *, size_t) noexcept
constexpr Allocator(const Arena::Allocator< U > &allocator) noexcept
constexpr Allocator(Arena &arena) noexcept
constexpr Deleter() noexcept=default
constexpr void operator()(T *ptr) const noexcept(noexcept(ptr->~T()))