9#ifndef ECS__MEMORY_CHUNK_ALLOCATOR_H__
10#define ECS__MEMORY_CHUNK_ALLOCATOR_H__
15#include <shared_mutex>
17namespace ECS {
namespace Memory {
19 template<
class OBJECT_TYPE,
size_t MAX_CHUNK_OBJECTS>
61 this->chunkEnd = this->chunkStart +
ALLOC_SIZE;
62 this->objects.clear();
79 class iterator :
public eastl::iterator<eastl::forward_iterator_tag, OBJECT_TYPE>
82 typename MemoryChunks::iterator
m_End;
89 iterator(
typename MemoryChunks::iterator
begin,
typename MemoryChunks::iterator
end) noexcept :
127 inline OBJECT_TYPE&
operator*() const noexcept {
return *(*m_CurrentObject); }
132 return ((this->m_CurrentChunk == other.m_CurrentChunk) && (this->m_CurrentObject == other.m_CurrentObject));
136 return ((this->m_CurrentChunk != other.m_CurrentChunk) && (this->m_CurrentObject != other.m_CurrentObject));
154 std::scoped_lock<std::shared_mutex> lock(
m_lock);
156 this->m_Chunks.push_back(
new MemoryChunk(allocator));
161 std::scoped_lock<std::shared_mutex> lock(
m_lock);
164 for (
auto chunk : this->m_Chunks)
166 for (
auto obj : chunk->objects)
167 ((OBJECT_TYPE*)obj)->~OBJECT_TYPE();
169 chunk->objects.clear();
172 Free((
void*)chunk->allocator->GetMemoryAddress0());
173 delete chunk->allocator;
174 chunk->allocator =
nullptr;
196 void* slot =
nullptr;
199 std::shared_lock<std::shared_mutex> lock(
m_lock);
201 for (
auto chunk : this->m_Chunks)
206 slot = chunk->allocator->allocate(
sizeof(OBJECT_TYPE),
alignof(OBJECT_TYPE));
209 chunk->objects.push_back((OBJECT_TYPE*)slot);
217 std::scoped_lock<std::shared_mutex> lock(
m_lock);
222 this->m_Chunks.push_front(newChunk);
226 assert(slot !=
nullptr &&
"Unable to create new object. Out of memory?!");
228 newChunk->
objects.push_back((OBJECT_TYPE*)slot);
249 std::scoped_lock<std::shared_mutex> lock(
m_lock);
250 const uptr adr =
reinterpret_cast<uptr>(object);
252 for (
auto chunk : this->m_Chunks)
254 if (chunk->chunkStart <= adr && adr < chunk->chunkEnd)
258 const size_t objectCount = chunk->objects.size();
260 chunk->objects.remove((OBJECT_TYPE*)object);
261 assert(chunk->objects.size() != objectCount &&
"Remove failed!");
264 chunk->allocator->free(
object);
269 assert(
false &&
"Failed to delete object. Memory corruption?!");
275 inline size_t size() noexcept {
return eastl::distance(
begin(),
end()); }
const void * GetMemoryAddress0() const
virtual void * allocate(size_t size, u8 alignment) override
const void * Allocate(size_t memSize, const char *user=nullptr)
MemoryChunk(Allocator *allocaor)
ObjectList::iterator m_CurrentObject
iterator & operator++() noexcept
OBJECT_TYPE & operator*() const noexcept
OBJECT_TYPE * operator()() const noexcept
OBJECT_TYPE * operator->() const noexcept
bool operator==(iterator &other) noexcept
MemoryChunks::iterator m_CurrentChunk
iterator(typename MemoryChunks::iterator begin, typename MemoryChunks::iterator end) noexcept
MemoryChunks::iterator m_End
bool operator!=(iterator &other) noexcept
MemoryChunkAllocator(const char *allocatorTag=nullptr) noexcept
eastl::list< OBJECT_TYPE * > ObjectList
eastl::list< MemoryChunk * > MemoryChunks
iterator begin() noexcept
static const size_t ALLOC_SIZE
Summary: Byte size to fit approx. MAX_CHUNK_OBJECTS objects.
Memory::Allocator::PoolAllocator Allocator
void DestroyObject(void *object)
const char * m_AllocatorTag
static const size_t MAX_OBJECTS