uwu
parent
3395a56bd3
commit
8af1db43c3
|
@ -23,6 +23,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <blt/std/utility.h>
|
#include <blt/std/utility.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
namespace blt
|
namespace blt
|
||||||
{
|
{
|
||||||
|
@ -304,7 +305,8 @@ namespace blt
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
explicit bump_allocator(blt::size_t size, Args&& ... defaults): buffer_(static_cast<pointer>(malloc(size * sizeof(type)))), offset_(0), size_(size)
|
explicit bump_allocator(blt::size_t size, Args&& ... defaults):
|
||||||
|
buffer_(static_cast<pointer>(malloc(size * sizeof(type)))), offset_(0), size_(size)
|
||||||
{
|
{
|
||||||
for (blt::size_t i = 0; i < size_; i++)
|
for (blt::size_t i = 0; i < size_; i++)
|
||||||
::new(&buffer_[i]) T(std::forward<Args>(defaults)...);
|
::new(&buffer_[i]) T(std::forward<Args>(defaults)...);
|
||||||
|
@ -350,19 +352,22 @@ namespace blt
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class multi_type_area_allocator
|
template<bool linked>
|
||||||
|
class multi_type_area_allocator;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class multi_type_area_allocator<false>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct pointer_view
|
|
||||||
{
|
|
||||||
blt::u8* p;
|
|
||||||
size_t n;
|
|
||||||
};
|
|
||||||
|
|
||||||
blt::u8* buffer_;
|
blt::u8* buffer_;
|
||||||
blt::u8* offset_;
|
blt::u8* offset_;
|
||||||
blt::size_t size_;
|
blt::size_t size_;
|
||||||
public:
|
public:
|
||||||
|
explicit multi_type_area_allocator(blt::size_t size): buffer_(static_cast<blt::u8*>(malloc(size))), offset_(buffer_), size_(size)
|
||||||
|
{}
|
||||||
|
|
||||||
|
explicit multi_type_area_allocator(blt::u8* buffer, blt::size_t size): buffer_(buffer), offset_(buffer), size_(size)
|
||||||
|
{}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] T* allocate()
|
[[nodiscard]] T* allocate()
|
||||||
|
@ -398,7 +403,118 @@ namespace blt
|
||||||
|
|
||||||
~multi_type_area_allocator()
|
~multi_type_area_allocator()
|
||||||
{
|
{
|
||||||
delete[] buffer_;
|
free(buffer_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class multi_type_area_allocator<true>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct block
|
||||||
|
{
|
||||||
|
blt::u8* buffer;
|
||||||
|
blt::size_t offset;
|
||||||
|
blt::size_t allocated_objects = 0;
|
||||||
|
blt::size_t deallocated_objects = 0;
|
||||||
|
};
|
||||||
|
std::vector<block> blocks;
|
||||||
|
blt::size_t size_;
|
||||||
|
|
||||||
|
void expand()
|
||||||
|
{
|
||||||
|
BLT_INFO("I have expanded!");
|
||||||
|
blocks.push_back({static_cast<blt::u8*>(malloc(size_)), 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* allocate_back()
|
||||||
|
{
|
||||||
|
auto& back = blocks.back();
|
||||||
|
size_t remaining_bytes = size_ - back.offset;
|
||||||
|
auto void_ptr = reinterpret_cast<void*>(&back.buffer[back.offset]);
|
||||||
|
auto new_ptr = static_cast<blt::u8*>(std::align(alignof(T), sizeof(T), void_ptr, remaining_bytes));
|
||||||
|
if (new_ptr == nullptr)
|
||||||
|
expand();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
back.offset += (back.buffer - new_ptr + sizeof(T));
|
||||||
|
back.allocated_objects++;
|
||||||
|
}
|
||||||
|
return static_cast<T*>(new_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit multi_type_area_allocator(blt::size_t size): size_(size)
|
||||||
|
{
|
||||||
|
expand();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
[[nodiscard]] T* allocate()
|
||||||
|
{
|
||||||
|
if (blocks.back().offset + sizeof(T) > size_)
|
||||||
|
expand();
|
||||||
|
if (auto ptr = allocate_back<T>(); ptr == nullptr)
|
||||||
|
{
|
||||||
|
BLT_INFO("Not enough space for me");
|
||||||
|
expand();
|
||||||
|
} else
|
||||||
|
return ptr;
|
||||||
|
if (auto ptr = allocate_back<T>(); ptr == nullptr)
|
||||||
|
throw std::bad_alloc();
|
||||||
|
else
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void deallocate(T* p)
|
||||||
|
{
|
||||||
|
auto* ptr = static_cast<blt::u8*>(p);
|
||||||
|
blt::i64 remove_index = -1;
|
||||||
|
for (auto e : blt::enumerate(blocks))
|
||||||
|
{
|
||||||
|
auto& block = e.second;
|
||||||
|
if (ptr >= block.buffer && ptr <= &block.buffer[block.offset])
|
||||||
|
{
|
||||||
|
block.deallocated_objects++;
|
||||||
|
if (block.deallocated_objects == block.allocated_objects)
|
||||||
|
remove_index = static_cast<blt::i64>(e.first);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (remove_index < 0)
|
||||||
|
return;
|
||||||
|
std::iter_swap(blocks.begin() + remove_index, blocks.end() - 1);
|
||||||
|
free(blocks.back().buffer);
|
||||||
|
BLT_DEBUG("I have freed a block!");
|
||||||
|
blocks.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
~multi_type_area_allocator()
|
||||||
|
{
|
||||||
|
for (auto& v : blocks)
|
||||||
|
free(v.buffer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue