"무례하긴, 순회야" - 객체 풀과 순회 인터페이스 구현하기

이창준, Changjoon Lee·2025년 7월 26일
1

Game Server Hyperion 🎮

목록 보기
2/14

프로젝트 : https://github.com/HoonInPark/ServerHyperion.git
본 포스트에 대한 내용은 feat/framesync 브랜치에 있다.

문제

원래 내가 만든 객체풀은 다음과 같이 구현돼 있었다.

#pragma once

#define SERVERHYPERION_EXPORT

#ifdef SERVERHYPERION_EXPORT
#define SERVERHYPERION_API __declspec(dllexport)
#else
#define SERVERHYPERION_API __declspec(dllimport)
#endif

#include <iostream>
#include <queue>
#include <utility>

using namespace std;

template <typename T>
class ObjPool
{
public:
	ObjPool() = default;

	template <class... P>
	ObjPool(size_t _InInitSize, P&&... params);

	shared_ptr<T> Acquire();
	void Return(shared_ptr<T>& _pInElem);

private:
	queue <shared_ptr< T >> m_Data;
};

template<typename T>
template<class ...P>
inline ObjPool<T>::ObjPool(size_t _InInitSize, P&&... params)
{
	for (size_t i = 0; i < _InInitSize; ++i)
	{
		m_Data.push(make_shared<T>(forward<P>(params)...));
	}
}

template<typename T>
inline shared_ptr<T> ObjPool<T>::Acquire()
{
	if (m_Data.empty()) 
		return nullptr;
	
	shared_ptr<T> RetPtr = m_Data.front();
	m_Data.pop();

	return RetPtr;
}

template<typename T>
inline void ObjPool<T>::Return(shared_ptr<T>& _pInElem)
{
	m_Data.push(_pInElem);
}

근데 queue <shared_ptr< T >> m_Data는 순회 불가능.
정 순회하고 싶으면 하나하나 디큐해서 값을 읽고 다시 집어넣어야 한다.

해결

std::queue는 내부에서 std::deque를 사용한다.
얘는 순회 가능하다.
노출하는 함수도 std::queue와 비슷.

#pragma once

#define SERVERHYPERION_EXPORT

#ifdef SERVERHYPERION_EXPORT
#define SERVERHYPERION_API __declspec(dllexport)
#else
#define SERVERHYPERION_API __declspec(dllimport)
#endif

#include <iostream>
#include <deque>
#include <utility>

using namespace std;

template <typename T>
class ObjPool
{
public:
	ObjPool() = default;

	template <class... P>
	ObjPool(size_t _InInitSize, P&&... params);

	shared_ptr<T> Acquire();
	void Return(shared_ptr<T>& _pInElem);

	inline auto begin() const { return m_Data.begin(); }
	inline auto end() const { return m_Data.end(); }

private:
	deque <shared_ptr< T >> m_Data;
};

template<typename T>
template<class ...P>
inline ObjPool<T>::ObjPool(size_t _InInitSize, P&&... params)
{
	for (size_t i = 0; i < _InInitSize; ++i)
	{
		m_Data.push_back(make_shared<T>(forward<P>(params)...));
	}
}

template<typename T>
inline shared_ptr<T> ObjPool<T>::Acquire()
{
	if (m_Data.empty()) 
		return nullptr;
	
	shared_ptr<T> RetPtr = m_Data.front();
	m_Data.pop_front();

	return RetPtr;
}

template<typename T>
inline void ObjPool<T>::Return(shared_ptr<T>& _pInElem)
{
	m_Data.push_back(_pInElem);
}

멤버인 m_Datastd::deque로 바꾸고 기존 동작과 동일하도록 함수만 조금 수정,
m_Databegin(), end()ObjPool클래스 외부에서 호출할 수 있도록 인터페이스 추가.

이렇게 하면 멤버 ObjPool<stClientInfo> m_ClientInfoPool에 대해 다음과 같이 for 루프에서 순회 가능.

for (const auto client : m_ClientInfoPool)
{
	// ...
}

"무례하긴, 순회야."

profile
C++ Game Developer

0개의 댓글