Skip to content

Commit

Permalink
Add arean impl. Add default ecs allocator as an example impl.
Browse files Browse the repository at this point in the history
  • Loading branch information
linuscu committed Oct 9, 2024
1 parent b2dfb4b commit 73b4298
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 10 deletions.
40 changes: 32 additions & 8 deletions packages/ecs/include/ecs/entityecs/ECSExt.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
#pragma once

#include <functional>
#include <tuple>
#include <typeinfo>
#include <vector>
#include <map>
#include <unordered_map>
#include <type_traits>
#include <memory>
#include <sstream>
#include <algorithm>
#include <iostream>

struct TickData {
float elapsedTime;
float deltaTime;
Expand All @@ -9,17 +21,29 @@ struct TickData {
#define ECS_TICK_TYPE TickData
#endif

template<class T>
class DefaultAllocator : public std::allocator<T> {
public:
DefaultAllocator() noexcept {}
DefaultAllocator(const DefaultAllocator& other) noexcept : std::allocator<T>(other) {}
template<class U>
DefaultAllocator(const DefaultAllocator<U>& other) noexcept : std::allocator<T>(other) {}
~DefaultAllocator() {}

void deallocate(T* const ptr, const size_t count) {
std::allocator<T>::deallocate(ptr, count);
}

T* allocate(const size_t count) {
return std::allocator<T>::allocate(count);
}
};

#define ECS_ALLOCATOR_TYPE DefaultAllocator<l::ecs::Entity>

#include "ECS.h"
#include "logging/LoggingAll.h"

#include <functional>
#include <tuple>
#include <typeinfo>
#include <vector>
#include <map>
#include <unordered_map>
#include <type_traits>

namespace l::ecs {

template<class ...Types>
Expand Down
34 changes: 32 additions & 2 deletions packages/memory/include/memory/Arena.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <memory>
#include <functional>
#include <string>
#include <unordered_map>
#include <map>
Expand All @@ -13,12 +15,40 @@
#include "logging/Log.h"
#include "meta/Reflection.h"

namespace l::container {
namespace l::memory {

struct MemoryBlock {
void* mBase = nullptr;
uint64_t mSize = 0u;
};

class Arena {
public:
Arena()
Arena();
~Arena();

std::vector<MemoryBlock> mBlocks;
};

std::unique_ptr<Arena> CreateArena();

// push some bytes onto the 'stack' - the way to allocate
void* ArenaPush(Arena* arena, uint64_t size);
void* ArenaPushZero(Arena* arena, uint64_t size);

// some macro helpers that I've found nice:
#define PushArray(arena, type, count) (type *)ArenaPush((arena), sizeof(type)*(count))
#define PushArrayZero(arena, type, count) (type *)ArenaPushZero((arena), sizeof(type)*(count))
#define PushStruct(arena, type) PushArray((arena), (type), 1)
#define PushStructZero(arena, type) PushArrayZero((arena), (type), 1)

// pop some bytes off the 'stack' - the way to free
void ArenaPop(Arena* arena, uint64_t size);

// get the # of bytes currently allocated.
uint64_t ArenaGetPos(Arena* arena);

// also some useful popping helpers:
void ArenaSetPosBack(Arena* arena, uint64_t pos);
void ArenaClear(Arena* arena);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,19 @@

namespace l::container {

union LLData {
struct Node {
Node* next;
Node* prev;
};
struct LinkedList {
Node* head;
Node* tail;
};
struct LinkedListNode {
Node* next;
Node* prev;
int value;
};
};
}
110 changes: 110 additions & 0 deletions packages/memory/source/common/Arena.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#pragma once

#include "memory/Arena.h"

#include "logging/Log.h"
#include "meta/Reflection.h"

#include <string>
#include <unordered_map>
#include <map>
#include <vector>
#include <algorithm> // For lower_bound
#include <typeinfo>
#include <optional>
#include <iterator> // For std::forward_iterator_tag
#include <cstddef> // For std::ptrdiff_t

namespace l::memory {

Arena::Arena() {
mBlocks.reserve(16);

}

Arena::~Arena() {

}

std::unique_ptr<Arena> CreateArena() {
return std::make_unique<Arena>();
}


// push some bytes onto the 'stack' - the way to allocate
void* ArenaPush(Arena* arena, uint64_t size) {
if (arena->mBlocks.empty()) {
arena->mBlocks.push_back({ malloc(size), size });
return arena->mBlocks.back().mBase;
}

MemoryBlock& lastBlock = arena->mBlocks.back();
if (lastBlock.mSize - (reinterpret_cast<uint64_t>(lastBlock.mBase) - reinterpret_cast<uint64_t>(arena->mBlocks.back().mBase)) >= size) {
return reinterpret_cast<void*>(reinterpret_cast<uint64_t>(lastBlock.mBase) + size);
}

arena->mBlocks.push_back({ malloc(size), size });
return arena->mBlocks.back().mBase;
}

void* ArenaPushZero(Arena* arena, uint64_t size) {
void* ptr = ArenaPush(arena, size);
memset(ptr, 0, size);
return ptr;
}

// some macro helpers that I've found nice:
#define PushArray(arena, type, count) (type *)ArenaPush((arena), sizeof(type)*(count))
#define PushArrayZero(arena, type, count) (type *)ArenaPushZero((arena), sizeof(type)*(count))
#define PushStruct(arena, type) PushArray((arena), (type), 1)
#define PushStructZero(arena, type) PushArrayZero((arena), (type), 1)

// pop some bytes off the 'stack' - the way to free
void ArenaPop(Arena* arena, uint64_t size) {
if (arena->mBlocks.empty()) {
LOG(LogError) << "Trying to pop from an empty arena";
return;
}

MemoryBlock& lastBlock = arena->mBlocks.back();
if (lastBlock.mSize - (reinterpret_cast<uint64_t>(lastBlock.mBase) - reinterpret_cast<uint64_t>(arena->mBlocks.back().mBase)) < size) {
LOG(LogError) << "Trying to pop more bytes than are available in the current block";
return;
}

lastBlock.mSize -= size;
}

// get the # of bytes currently allocated.
uint64_t ArenaGetPos(Arena* arena) {
if (arena->mBlocks.empty()) {
return 0;
}

MemoryBlock& lastBlock = arena->mBlocks.back();
return lastBlock.mSize - (reinterpret_cast<uint64_t>(lastBlock.mBase) - reinterpret_cast<uint64_t>(arena->mBlocks.back().mBase));
}

// also some useful popping helpers:
void ArenaSetPosBack(Arena* arena, uint64_t pos) {
if (arena->mBlocks.empty()) {
LOG(LogError) << "Trying to set position in an empty arena";
return;
}

MemoryBlock& lastBlock = arena->mBlocks.back();
if (lastBlock.mSize - (reinterpret_cast<uint64_t>(lastBlock.mBase) - reinterpret_cast<uint64_t>(arena->mBlocks.back().mBase)) < pos) {
LOG(LogError) << "Trying to set position past the end of the current block";
return;
}

lastBlock.mSize = pos;
}

void ArenaClear(Arena* arena) {
for (MemoryBlock& block : arena->mBlocks) {
free(block.mBase);
}
arena->mBlocks.clear();
}
}
33 changes: 33 additions & 0 deletions packages/memory/source/common/LinkedListArray.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <string>
#include <unordered_map>
#include <map>
#include <vector>
#include <algorithm> // For lower_bound
#include <typeinfo>
#include <optional>
#include <iterator> // For std::forward_iterator_tag
#include <cstddef> // For std::ptrdiff_t

#include "logging/Log.h"
#include "meta/Reflection.h"

namespace l::container {

union LLData {
struct Node {
Node* next;
Node* prev;
};
struct LinkedList {
Node* head;
Node* tail;
};
struct LinkedListNode {
Node* next;
Node* prev;
int value;
};
};
}

0 comments on commit 73b4298

Please sign in to comment.