이번에는 Object Pool에 대해 설명드리겠습니다. Object Pool은 간단히 클래스마다 전용 Memory Pool을 만들어 주는 것입니다.
이렇게 클래스마다 따로 만들어주는 이유는 버그가 발생하면 해당 클래스의 Object Pool만 확인해도 되니 찾기 좋다는 점 등 때문입니다.
그래서 template을 이용해 각 클래스마다 하나의 전용 MemoryPool을 만들어 주는 일을 해볼 것입니다.
template<typename Type>
class MyObjectPool {
public:
template<typename... Args>
static Type* Pop(Args&&... args) {
Type* memory = static_cast<Type*>(MyMemoryHeader::AttachHeader(s_pool.Pop(), s_allocSize));
new(memory)Type(forward<Args>(args)...);
return memory;
}
static void Push(Type* ptr) {
ptr->~Type();
s_pool.Push(MyMemoryHeader::DetachHeader(ptr));
}
private:
static int32 s_allocSize;
static MyMemoryPool s_pool;
};
template<typename Type>
int32 MyObjectPool<Type>::s_allocSize = sizeof(Type) + sizeof(MyMemoryHeader);
template<typename Type>
MyMemoryPool MyObjectPool<Type>::s_pool{ s_allocSize };
int main() {
Person* k = ObjectPool<Person>::Pop();
ObjectPool<Person>::Push(k);
}
이런 식으로 사용할 수 있습니다. 다만 사용할 때마다 저런 식으로 해야하는 것은 상당히 귀찮은 일입니다. 잊어먹고 xdelete를 사용할 수 있기 때문입니다.
그래서 많이 사용하는 shared_ptr 형식으로 만들고 간편하게 사용할 수 있도록 만들어보겠습니다.
static shared_ptr<Type> MakeShared() {
shared_ptr<Type> ptr = { Pop(), Push };
return ptr;
}
shared_ptr<Person> k = ObjectPool<Person>::MakeShared();
이런 느낌으로 사용할 수 있을 것입니다.
더 나아가 MemoryPool도 이런 식으로 만들어주면 편할 것입니다.
template<typename Type>
shared_ptr<Type> MakeShared() {
return shared_ptr<Type>{ xxnew<Type>(), xxdelete<Type> };
}