feat(mempool): add MemPool

This commit is contained in:
fallenoak 2023-01-01 22:50:45 -06:00 committed by GitHub
parent 90246804d0
commit 33be859acd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 218 additions and 0 deletions

View file

@ -1,6 +1,7 @@
file(GLOB COMMON_SOURCES
"*.cpp"
"datastore/*.cpp"
"mempool/*.cpp"
"objectalloc/*.cpp"
"ref/*.cpp"
"string/*.cpp"

6
common/MemPool.hpp Normal file
View file

@ -0,0 +1,6 @@
#ifndef COMMON_MEM_POOL_HPP
#define COMMON_MEM_POOL_HPP
#include "common/mempool/MemPool.hpp"
#endif

View file

@ -0,0 +1,61 @@
#include "common/mempool/MemChunk.hpp"
#include <storm/Memory.hpp>
struct MemBlock {
void* next;
};
MemChunk::MemChunk(size_t blockSize, size_t a2) {
this->m_blockSize = blockSize;
this->m_numBlocks = a2 / blockSize;
size_t v4 = blockSize * (a2 / blockSize);
this->m_unk2 = v4;
void* data = SMemAlloc(v4, __FILE__, __LINE__, 0x0);
this->m_memblocks = data;
this->m_free = data;
auto bytes = static_cast<char*>(data);
auto last = &bytes[this->m_unk2 - this->m_blockSize];
MemBlock* block;
while ((uintptr_t)bytes < (uintptr_t)last) {
block = reinterpret_cast<MemBlock*>(bytes);
// Drop a pointer to the next block
block->next = &bytes[this->m_blockSize];
// Move to the next block
bytes += this->m_blockSize;
}
// Drop null pointer in last block
block = reinterpret_cast<MemBlock*>(bytes);
block->next = nullptr;
}
bool MemChunk::Contains(void* ptr) {
return (uintptr_t)ptr >= (uintptr_t)this->m_memblocks && (uintptr_t)ptr < (uintptr_t)this->m_memblocks + this->m_unk2;
}
void* MemChunk::MemAlloc() {
auto block = reinterpret_cast<MemBlock*>(this->m_free);
if (block) {
this->m_free = block->next;
this->m_numBlocks--;
return static_cast<void*>(block);
} else {
return nullptr;
}
}
void MemChunk::MemFree(void* ptr) {
auto block = reinterpret_cast<MemBlock*>(ptr);
block->next = this->m_free;
this->m_free = block;
this->m_numBlocks++;
}

View file

@ -0,0 +1,22 @@
#ifndef COMMON_MEMPOOL_MEM_CHUNK_HPP
#define COMMON_MEMPOOL_MEM_CHUNK_HPP
#include <cstdlib>
class MemChunk {
public:
// Member variables
void* m_memblocks;
void* m_free;
size_t m_unk2;
size_t m_blockSize;
size_t m_numBlocks;
// Member functions
MemChunk(size_t blockSize, size_t a2);
bool Contains(void* ptr);
void* MemAlloc();
void MemFree(void* ptr);
};
#endif

View file

@ -0,0 +1,67 @@
#include "common/mempool/MemPool.hpp"
#include "common/mempool/MemChunk.hpp"
MemPool::MemPool() {
TSFixedArray<MemChunk*>(this->m_memchunks);
}
void MemPool::Init(size_t blockSize, size_t a2) {
this->m_unk3 = blockSize * (a2 / blockSize);
this->m_blockSize = blockSize;
this->m_unk5 = a2 / blockSize;
}
void* MemPool::MemAlloc() {
auto count = this->m_memchunks.Count();
// If chunks already exist, try allocate off of one of them
for (int32_t i = 0; i < count; i++) {
auto chunk = this->m_memchunks[i];
auto mem = chunk->MemAlloc();
if (mem) {
return mem;
}
}
// No chunks exist, or all existing chunks are full
// Create a new chunk and allocate off of it
this->m_memchunks.SetCount(count + 1);
void* m = SMemAlloc(sizeof(MemChunk), __FILE__, __LINE__, 0x0);
MemChunk* chunk = new (m) MemChunk(this->m_blockSize, this->m_unk3);
this->m_memchunks[count] = chunk;
return chunk->MemAlloc();
}
int32_t MemPool::MemFree(void* ptr) {
auto count = this->m_memchunks.Count();
if (count == 0) {
return 0;
}
int32_t v3 = 0;
MemChunk* v4;
while (1) {
v4 = this->m_memchunks[v3];
if (v4->Contains(ptr)) {
break;
}
if (++v3 >= count) {
return 0;
}
}
auto relevantChunk = this->m_memchunks[v3];
relevantChunk->MemFree(ptr);
return 1;
}

View file

@ -0,0 +1,25 @@
#ifndef COMMON_MEMPOOL_MEM_POOL_HPP
#define COMMON_MEMPOOL_MEM_POOL_HPP
#include <cstdint>
#include <cstdlib>
#include <storm/Array.hpp>
class MemChunk;
class MemPool {
public:
// Member variables
TSFixedArray<MemChunk*> m_memchunks;
size_t m_unk3;
size_t m_blockSize;
size_t m_unk5;
// Member functions
MemPool();
void Init(size_t blockSize, size_t a2);
void* MemAlloc();
int32_t MemFree(void* ptr);
};
#endif

36
test/MemPool.cpp Normal file
View file

@ -0,0 +1,36 @@
#include "common/MemPool.hpp"
#include "test/Test.hpp"
TEST_CASE("MemPool::MemPool", "[mempool]") {
SECTION("constructs new mem pool") {
MemPool pool;
SUCCEED();
}
}
TEST_CASE("MemPool::Init", "[mempool]") {
SECTION("inits mem pool") {
MemPool pool;
pool.Init(16, 16 << 10);
SUCCEED();
}
}
TEST_CASE("MemPool::MemAlloc", "[mempool]") {
SECTION("allocates pointer to new free memory") {
MemPool pool;
pool.Init(16, 16 << 10);
auto ptr = pool.MemAlloc();
REQUIRE(ptr);
}
}
TEST_CASE("MemPool::MemFree", "[mempool]") {
SECTION("frees allocated pointer") {
MemPool pool;
pool.Init(16, 16 << 10);
auto ptr = pool.MemAlloc();
pool.MemFree(ptr);
SUCCEED();
}
}