mirror of
https://github.com/thunderbrewhq/common.git
synced 2025-12-12 03:02:29 +00:00
feat(mempool): add MemPool
This commit is contained in:
parent
90246804d0
commit
33be859acd
7 changed files with 218 additions and 0 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
file(GLOB COMMON_SOURCES
|
file(GLOB COMMON_SOURCES
|
||||||
"*.cpp"
|
"*.cpp"
|
||||||
"datastore/*.cpp"
|
"datastore/*.cpp"
|
||||||
|
"mempool/*.cpp"
|
||||||
"objectalloc/*.cpp"
|
"objectalloc/*.cpp"
|
||||||
"ref/*.cpp"
|
"ref/*.cpp"
|
||||||
"string/*.cpp"
|
"string/*.cpp"
|
||||||
|
|
|
||||||
6
common/MemPool.hpp
Normal file
6
common/MemPool.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef COMMON_MEM_POOL_HPP
|
||||||
|
#define COMMON_MEM_POOL_HPP
|
||||||
|
|
||||||
|
#include "common/mempool/MemPool.hpp"
|
||||||
|
|
||||||
|
#endif
|
||||||
61
common/mempool/MemChunk.cpp
Normal file
61
common/mempool/MemChunk.cpp
Normal 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++;
|
||||||
|
}
|
||||||
22
common/mempool/MemChunk.hpp
Normal file
22
common/mempool/MemChunk.hpp
Normal 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
|
||||||
67
common/mempool/MemPool.cpp
Normal file
67
common/mempool/MemPool.cpp
Normal 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;
|
||||||
|
}
|
||||||
25
common/mempool/MemPool.hpp
Normal file
25
common/mempool/MemPool.hpp
Normal 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
36
test/MemPool.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue