diff --git a/include/blt/std/allocator.h b/include/blt/std/allocator.h index f4c227e..dd9071c 100644 --- a/include/blt/std/allocator.h +++ b/include/blt/std/allocator.h @@ -26,6 +26,11 @@ #include #include #include "logging.h" +#include + + #ifdef __unix__ + #include + #endif namespace blt { @@ -422,10 +427,9 @@ namespace blt private: struct block { + blt::size_t allocated_objects = 0; blt::u8* buffer = nullptr; blt::u8* offset = nullptr; - blt::size_t allocated_objects = 0; - blt::size_t deallocated_objects = 0; explicit block(blt::u8* buffer): buffer(buffer), offset(buffer) {} @@ -434,11 +438,14 @@ namespace blt ALLOC allocator; std::vector> blocks; blt::size_t size_; + blt::size_t allocations = 0; + blt::size_t deallocations = 0; void expand() { auto ptr = static_cast(allocator.allocate(size_)); blocks.push_back(block{ptr}); + allocations++; } template @@ -483,23 +490,22 @@ namespace blt void deallocate(T* p) { auto* ptr = reinterpret_cast(p); - blt::i64 remove_index = -1; for (auto e : blt::enumerate(blocks)) { auto& block = e.second; if (ptr >= block.buffer && ptr <= block.offset) { - block.deallocated_objects++; - if (block.deallocated_objects == block.allocated_objects) - remove_index = static_cast(e.first); - break; + block.allocated_objects--; + if (block.allocated_objects == 0) + { + std::iter_swap(blocks.begin() + e.first, blocks.end() - 1); + allocator.deallocate(blocks.back().buffer, size_); + blocks.pop_back(); + deallocations++; + } + return; } } - if (remove_index < 0) - return; - std::iter_swap(blocks.begin() + remove_index, blocks.end() - 1); - allocator.deallocate(blocks.back().buffer, size_); - blocks.pop_back(); } template @@ -524,11 +530,120 @@ namespace blt ~bump_allocator() { + if (allocations != deallocations) + BLT_WARN("Allocator has blocks which have not been deallocated! Destructors might not have been called!"); for (auto& v : blocks) allocator.deallocate(v.buffer, size_); } }; + template + class bump_allocator2 + { + // power of two + static_assert(BLOCK_SIZE && ((BLOCK_SIZE & (BLOCK_SIZE - 1)) == 0)); + private: + struct block + { + struct + { + blt::size_t allocated_objects = 0; + block* next = nullptr; + blt::u8* offset = nullptr; + } metadata; + blt::u8 buffer[BLOCK_SIZE - sizeof(metadata)]{}; + + block() + { + metadata.offset = buffer; + } + }; + + block* base = nullptr; + block* head = nullptr; + + block* allocate_block() + { + auto* buffer = reinterpret_cast(std::aligned_alloc(BLOCK_SIZE, BLOCK_SIZE)); + construct(buffer); + return buffer; + } + + void allocate_forward() + { + auto* block = allocate_block(); + head->metadata.next = block; + head = block; + } + + template + T* allocate_back() + { + size_t remaining_bytes = BLOCK_SIZE - static_cast(head->metadata.offset - head->buffer); + +// auto& back = blocks.back(); +// size_t remaining_bytes = size_ - static_cast(back.offset - back.buffer); +// auto pointer = static_cast(back.offset); +// const auto aligned_address = std::align(alignof(T), sizeof(T), pointer, remaining_bytes); +// if (aligned_address != nullptr) +// { +// back.offset = static_cast(aligned_address) + sizeof(T); +// back.allocated_objects++; +// } +// +// return static_cast(aligned_address); + } + + public: + bump_allocator2() + { + base = head = allocate_block(); + }; + + template + [[nodiscard]] T* allocate() + { + + } + + template + void deallocate(T* p) + { + + } + + template + [[nodiscard]] T* emplace(Args&& ... args) + { + const auto allocated_memory = allocate(); + return new(allocated_memory) T{std::forward(args)...}; + } + + template + inline void construct(U* p, Args&& ... args) + { + ::new((void*) p) U(std::forward(args)...); + } + + template + inline void destroy(U* p) + { + if (p != nullptr) + p->~U(); + } + + ~bump_allocator2() + { + block* next = base; + while (next != nullptr) + { + auto* after = next->metadata.next; + free(next); + next = after; + } + } + }; + template class constexpr_allocator {