#pragma once #include #include #include class memory_pool { public: memory_pool(const size_t chunk_size, const size_t chunks_per_block) : chunk_size_(chunk_size), chunks_per_block_(chunks_per_block), current_block_(nullptr), free_list_(nullptr) { allocate_block(); } memory_pool(memory_pool&& other) noexcept : chunk_size_(other.chunk_size_), chunks_per_block_(other.chunks_per_block_), blocks_(std::move(other.blocks_)), current_block_(other.current_block_), free_list_(other.free_list_) { other.current_block_ = nullptr; other.free_list_ = nullptr; } ~memory_pool() { for (void* block : blocks_) { delete[] static_cast(block); } } auto allocate() -> void* { if (!free_list_) { allocate_block(); } std::lock_guard lock(mutex_); void* chunk = free_list_; free_list_ = *static_cast(free_list_); return chunk; } void deallocate(void* chunk) { std::lock_guard lock(mutex_); *static_cast(chunk) = free_list_; free_list_ = chunk; } private: void allocate_block() { const size_t block_size = chunk_size_ * chunks_per_block_; const auto new_block = new char[block_size]; { std::lock_guard lock(mutex_); blocks_.push_back(new_block); current_block_ = new_block; } for (size_t i = 0; i < chunks_per_block_; ++i) { void* chunk = new_block + i * chunk_size_; deallocate(chunk); } } size_t chunk_size_; size_t chunks_per_block_; std::vector blocks_; void* current_block_; void* free_list_; std::mutex mutex_; }; template class obj_mempool { public: template static auto construct(Args&&... args) -> T* { auto obj = alloc(); new (obj) T(std::forward(args)...); return obj; } static auto construct() -> T* { auto obj = alloc(); new (obj) T(); return obj; } static void free(T* p) { p->~T(); deallocate(p); } static void free_all() { for (auto obj : objs_) { obj->~T(); pool_.deallocate(obj); } objs_.clear(); } static auto objs() -> const std::vector& { return objs_; } static auto has_obj(T* p) -> bool { return std::find(objs_.begin(), objs_.end(), p) != objs_.end(); } static auto safe_free(T* p) -> bool { if (has_obj(p)) { free(p); return true; } return false; } static auto alloc() -> T* { T* p = static_cast(pool_.allocate()); objs_.push_back(p); return p; } static void deallocate(T* p) { pool_.deallocate(p); auto e = std::ranges::remove(objs_, p); objs_.erase(e.begin(), e.end()); } private: inline static auto pool_ = memory_pool(sizeof(T), 64); inline static std::vector objs_; }; template class pool_obj { public: auto operator new(size_t size) -> void* { return obj_mempool::alloc(); } void operator delete(void* p) { obj_mempool::deallocate(static_cast(p)); } };