Files
m2dev-client-src/src/EterLib/Pool.h
d1str4ught 24b1ca495b pool FreeAll and Destroy fixed
there could have been memory leaks and undefined behaviors if the objects destructors were not called and the object it pooled contained objects that are constructed (like std::string)
2025-08-23 19:48:15 +02:00

98 lines
1.4 KiB
C++

#pragma once
#include "EterBase/Debug.h"
template<typename T>
class CDynamicPool
{
public:
CDynamicPool()
{
}
virtual ~CDynamicPool()
{
Destroy();
}
void Clear()
{
Destroy();
}
void Destroy()
{
FreeAll();
for (T* p : m_Chunks)
::free(p);
m_Free.clear();
m_Data.clear();
m_Chunks.clear();
}
void Create(size_t chunkSize)
{
m_uChunkSize = chunkSize;
}
template<class... _Types>
T* Alloc(_Types&&... _Args)
{
if (m_Free.empty())
Grow();
T* p = m_Free.back();
m_Free.pop_back();
return new(p) T(std::forward<_Types>(_Args)...);
}
void Free(T* p)
{
p->~T();
m_Free.push_back(p);
}
void FreeAll()
{
for (T* p : m_Data) {
if (std::find(m_Free.begin(), m_Free.end(), p) == m_Free.end()) {
p->~T();
}
}
m_Free = m_Data;
}
DWORD GetCapacity()
{
return m_Data.size();
}
protected:
void Grow() noexcept
{
size_t uChunkSize = m_uChunkSize + m_uChunkSize * m_Chunks.size();
T* pStart = (T*) ::malloc(uChunkSize * sizeof(T));
m_Chunks.push_back(pStart);
m_Data.reserve(m_Data.size() + uChunkSize);
m_Free.reserve(m_Free.size() + uChunkSize);
for (size_t i = 0; i < uChunkSize; ++i)
{
m_Data.push_back(pStart + i);
m_Free.push_back(pStart + i);
}
}
protected:
size_t m_uChunkSize = 64;
std::vector<T*> m_Data;
std::vector<T*> m_Free;
std::vector<T*> m_Chunks;
};