13class stack_allocator {
15 using padding_t = uint8_t;
26 stack_allocator(
void* ptr, std::size_t size) : _start(static_cast<char*>(ptr)), _size(size) {
29 stack_allocator(
const stack_allocator& rhs) =
delete;
30 stack_allocator& operator=(
const stack_allocator& rhs) =
delete;
34 stack_allocator(stack_allocator&& rhs) noexcept :
35 _start(std::exchange(rhs._start,
nullptr)), _size(std::exchange(rhs._size, 0)) {
41 stack_allocator& operator=(stack_allocator&& rhs)
noexcept {
42 _start = std::exchange(rhs._start,
nullptr);
43 _size = std::exchange(rhs._size, 0);
51 auto allocate(std::size_t bytes, std::size_t alignment =
alignof(std::max_align_t))
noexcept ->
void* {
52 assert(
is_power_of_2(alignment) &&
"Alignment must be a power of two");
53 assert((alignment <= std::numeric_limits<padding_t>::max()) &&
"Alignment is out of range");
56 char* top = _start + _offset;
58 void* ptr = top +
sizeof(alloc_header);
60 auto remaining_space = _size - _offset -
sizeof(alloc_header);
62 void* aligned_ptr = std::align(alignment, bytes, ptr, remaining_space);
68 auto padding =
static_cast<padding_t
>(
static_cast<char*
>(aligned_ptr) - top);
70 _offset += padding + bytes;
73 new (
static_cast<char*
>(aligned_ptr) -
sizeof(alloc_header)) alloc_header{ padding };
80 void deallocate(
void* ptr)
noexcept {
81 assert((ptr < _start + _size) && (ptr >= _start) &&
"Outside allocation range");
84 auto* hdr =
reinterpret_cast<alloc_header*
>(
static_cast<char*
>(ptr) -
sizeof(alloc_header));
86 _offset =
static_cast<char*
>(ptr) - hdr->padding - _start;
93 [[nodiscard]]
auto remaining() const noexcept ->
std::
size_t {
94 return (_size - _offset);
98 void reset() noexcept {
104 std::size_t _offset{};
Definition component.hpp:17
constexpr auto is_power_of_2(auto value) -> bool
Check if value is a power of 2.
Definition bits.hpp:17