76 lines
2.3 KiB
C++
76 lines
2.3 KiB
C++
|
#ifndef _OBJECT_POOL_HPP_
|
||
|
#define _OBJECT_POOL_HPP_
|
||
|
|
||
|
#include <list>
|
||
|
#include <mutex>
|
||
|
|
||
|
template<typename OBJECT, typename MUTEX_TYPE = std::mutex, uint32_t INIT_ALLOC_SIZE = 1024>
|
||
|
class ObjectPool {
|
||
|
protected:
|
||
|
struct ObjectWrapper {
|
||
|
OBJECT real_obj;
|
||
|
ObjectWrapper* next;
|
||
|
};
|
||
|
public:
|
||
|
~ObjectPool() {
|
||
|
for(auto& block : mem_blocks) {
|
||
|
delete[] block;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename ... ARGS>
|
||
|
OBJECT* Alloc(ARGS... args) {
|
||
|
std::lock_guard<MUTEX_TYPE> locker(mutex);
|
||
|
if(free_blocks == nullptr) {
|
||
|
auto mem_block = new uint8_t[sizeof(ObjectWrapper) * alloc_size];
|
||
|
mem_blocks.push_back(mem_block);
|
||
|
ObjectWrapper* first = reinterpret_cast<ObjectWrapper*>(mem_block);
|
||
|
free_blocks = first + 1;
|
||
|
free_blocks->next = reinterpret_cast<ObjectWrapper*>(alloc_size - 2);
|
||
|
alloc_size *= 2;
|
||
|
if(alloc_size > 0x10000)
|
||
|
alloc_size = 0x10000;
|
||
|
return new(&first->real_obj) OBJECT(std::forward<ARGS>(args)...);
|
||
|
} else {
|
||
|
OBJECT* object = nullptr;
|
||
|
uintptr_t left_count = reinterpret_cast<uintptr_t>(free_blocks->next);
|
||
|
if(left_count <= 0x10000 && left_count > 0) {
|
||
|
object = &free_blocks->real_obj;
|
||
|
free_blocks++;
|
||
|
free_blocks->next = reinterpret_cast<ObjectWrapper*>(left_count - 1);
|
||
|
} else {
|
||
|
object = &free_blocks->real_obj;
|
||
|
if(left_count < 1)
|
||
|
free_blocks = nullptr;
|
||
|
else
|
||
|
free_blocks = free_blocks->next;
|
||
|
}
|
||
|
return new(object) OBJECT(std::forward<ARGS>(args)...);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Recycle(OBJECT* object) {
|
||
|
std::lock_guard<MUTEX_TYPE> locker(mutex);
|
||
|
object->~OBJECT();
|
||
|
ObjectWrapper* wrapper = reinterpret_cast<ObjectWrapper*>(object);
|
||
|
wrapper->next = free_blocks;
|
||
|
free_blocks = wrapper;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
uint32_t alloc_size = INIT_ALLOC_SIZE;
|
||
|
ObjectWrapper* free_blocks = nullptr;
|
||
|
std::list<uint8_t*> mem_blocks;
|
||
|
MUTEX_TYPE mutex;
|
||
|
};
|
||
|
|
||
|
struct LockLess {
|
||
|
void lock() {}
|
||
|
void unlock() {}
|
||
|
};
|
||
|
|
||
|
template<typename OBJECT, uint32_t INIT_ALLOC_SIZE = 1024>
|
||
|
using ObjectPoolNoLock = ObjectPool<OBJECT, LockLess, INIT_ALLOC_SIZE>;
|
||
|
|
||
|
#endif
|