Object Pool은 동일한 타입의 객체를 메모리 풀로 재사용하도록 설계된 자료구조입니다. 각 객체 타입별로 메모리 풀이 따로 생성되어, 메모리 오염 및 관리 이슈를 줄이고 성능을 높일 수 있습니다.
📌 기존 Memory Pool이 객체의 크기 기준으로 풀을 구성했다면, Object Pool은 타입 기준으로 구성합니다.
static MemoryPool 생성Pop으로 객체 생성, Push로 객체 반환placement new와 소멸자 수동 호출 사용shared_ptr 커스텀 deleter를 이용해 자동 관리 가능#pragma once
#include "Types.h"
#include "MemoryPool.h"
template<typename Type>
class ObjectPool
{
public:
template<typename... Args>
static Type* Pop(Args&&... args)
{
#ifdef _STOMP
MemoryHeader* ptr = reinterpret_cast<MemoryHeader*>(StompAllocator::Alloc(s_allocSize));
Type* memory = static_cast<Type*>(MemoryHeader::AttachHeader(ptr, s_allocSize));
#else
Type* memory = static_cast<Type*>(MemoryHeader::AttachHeader(s_pool.Pop(), s_allocSize));
#endif
new(memory) Type(forward<Args>(args)...); // placement new
return memory;
}
static void Push(Type* obj)
{
obj->~Type();
#ifdef _STOMP
StompAllocator::Release(MemoryHeader::DetachHeader(obj));
#else
s_pool.Push(MemoryHeader::DetachHeader(obj));
#endif
}
static shared_ptr<Type> MakeShared()
{
shared_ptr<Type> ptr = { Pop(), Push };
return ptr;
}
private:
static int32 s_allocSize;
static MemoryPool s_pool;
};
template<typename Type>
int32 ObjectPool<Type>::s_allocSize = sizeof(Type) + sizeof(MemoryHeader);
template<typename Type>
MemoryPool ObjectPool<Type>::s_pool{ s_allocSize };
template을 통해 타입마다 static 멤버 별도 생성Pop()은 placement new로 객체 생성Push()는 소멸자 호출 후 풀에 반납_STOMP 정의 여부에 따라 StompAllocator 사용 가능메모리 오염 디버깅에 특화된 StompAllocator를 사용할 수 있도록 #ifdef _STOMP 조건부 컴파일을 추가했습니다.
_STOMP가 정의되면: StompAllocator 사용
Memory.cpp,ObjectPool.h에 모두 적용되어 테스트 모드 전환이 유연해집니다.
Knight* k = ObjectPool<Knight>::Pop();
delete k; // ❌ 위험한 사용!
shared_ptr<Knight> sptr = ObjectPool<Knight>::MakeShared();
MakeShared()는 Pop과 Push를 묶어 shared_ptr을 생성해줍니다.Push()가 호출되므로 메모리 관리가 안전합니다.class Knight
{
public:
int32 _hp = rand() % 1000;
};
int main()
{
// 수동 방식
Knight* knight = ObjectPool<Knight>::Pop();
ObjectPool<Knight>::Push(knight);
// 스마트 포인터 방식
shared_ptr<Knight> sptr = ObjectPool<Knight>::MakeShared();
shared_ptr<Knight> sptr2 = MakeShared<Knight>(); // 메모리 풀 기반
}
참고:
MakeShared<Knight>()는 일반 MemoryPool을 사용하는 버전입니다.