more allocator nonsense
parent
be4a61cc80
commit
a71adc328e
|
@ -26,6 +26,11 @@
|
||||||
#include <blt/compatibility.h>
|
#include <blt/compatibility.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#ifdef __unix__
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace blt
|
namespace blt
|
||||||
{
|
{
|
||||||
|
@ -422,10 +427,9 @@ namespace blt
|
||||||
private:
|
private:
|
||||||
struct block
|
struct block
|
||||||
{
|
{
|
||||||
|
blt::size_t allocated_objects = 0;
|
||||||
blt::u8* buffer = nullptr;
|
blt::u8* buffer = nullptr;
|
||||||
blt::u8* offset = 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)
|
explicit block(blt::u8* buffer): buffer(buffer), offset(buffer)
|
||||||
{}
|
{}
|
||||||
|
@ -434,11 +438,14 @@ namespace blt
|
||||||
ALLOC<blt::u8> allocator;
|
ALLOC<blt::u8> allocator;
|
||||||
std::vector<block, ALLOC<block>> blocks;
|
std::vector<block, ALLOC<block>> blocks;
|
||||||
blt::size_t size_;
|
blt::size_t size_;
|
||||||
|
blt::size_t allocations = 0;
|
||||||
|
blt::size_t deallocations = 0;
|
||||||
|
|
||||||
void expand()
|
void expand()
|
||||||
{
|
{
|
||||||
auto ptr = static_cast<blt::u8*>(allocator.allocate(size_));
|
auto ptr = static_cast<blt::u8*>(allocator.allocate(size_));
|
||||||
blocks.push_back(block{ptr});
|
blocks.push_back(block{ptr});
|
||||||
|
allocations++;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -483,23 +490,22 @@ namespace blt
|
||||||
void deallocate(T* p)
|
void deallocate(T* p)
|
||||||
{
|
{
|
||||||
auto* ptr = reinterpret_cast<blt::u8*>(p);
|
auto* ptr = reinterpret_cast<blt::u8*>(p);
|
||||||
blt::i64 remove_index = -1;
|
|
||||||
for (auto e : blt::enumerate(blocks))
|
for (auto e : blt::enumerate(blocks))
|
||||||
{
|
{
|
||||||
auto& block = e.second;
|
auto& block = e.second;
|
||||||
if (ptr >= block.buffer && ptr <= block.offset)
|
if (ptr >= block.buffer && ptr <= block.offset)
|
||||||
{
|
{
|
||||||
block.deallocated_objects++;
|
block.allocated_objects--;
|
||||||
if (block.deallocated_objects == block.allocated_objects)
|
if (block.allocated_objects == 0)
|
||||||
remove_index = static_cast<blt::i64>(e.first);
|
{
|
||||||
break;
|
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<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
|
@ -524,11 +530,120 @@ namespace blt
|
||||||
|
|
||||||
~bump_allocator()
|
~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)
|
for (auto& v : blocks)
|
||||||
allocator.deallocate(v.buffer, size_);
|
allocator.deallocate(v.buffer, size_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<blt::size_t BLOCK_SIZE = 4096 * 16>
|
||||||
|
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<block*>(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<typename T>
|
||||||
|
T* allocate_back()
|
||||||
|
{
|
||||||
|
size_t remaining_bytes = BLOCK_SIZE - static_cast<size_t>(head->metadata.offset - head->buffer);
|
||||||
|
|
||||||
|
// auto& back = blocks.back();
|
||||||
|
// size_t remaining_bytes = size_ - static_cast<size_t>(back.offset - back.buffer);
|
||||||
|
// auto pointer = static_cast<void*>(back.offset);
|
||||||
|
// const auto aligned_address = std::align(alignof(T), sizeof(T), pointer, remaining_bytes);
|
||||||
|
// if (aligned_address != nullptr)
|
||||||
|
// {
|
||||||
|
// back.offset = static_cast<blt::u8*>(aligned_address) + sizeof(T);
|
||||||
|
// back.allocated_objects++;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return static_cast<T*>(aligned_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bump_allocator2()
|
||||||
|
{
|
||||||
|
base = head = allocate_block();
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
[[nodiscard]] T* allocate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void deallocate(T* p)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
[[nodiscard]] T* emplace(Args&& ... args)
|
||||||
|
{
|
||||||
|
const auto allocated_memory = allocate<T>();
|
||||||
|
return new(allocated_memory) T{std::forward<Args>(args)...};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class U, class... Args>
|
||||||
|
inline void construct(U* p, Args&& ... args)
|
||||||
|
{
|
||||||
|
::new((void*) p) U(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
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<typename T>
|
template<typename T>
|
||||||
class constexpr_allocator
|
class constexpr_allocator
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue