hproselet/objpool.hpp

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