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