320x100
메모리 풀은 미리 사용할 객체들을 할당해놓고 필요할 때 가져가고 사용 후엔 반환하며 쓰는 개념이다.
예전엔 다음과 같이 각 메모리들을 할당해두고 각 메모리에 다음 사용할 객체의 포인터 주소를 넣는 식으로 linked list로 구현한 버전을 찾아볼 수 있었다.
template <typename T, size_t ALLOC_COUNT>
class ObjectPool
{
using uchar = unsigned char;
public:
static void* operator new(size_t size)
{
ScopeLock sl(&lock_);
if (nullptr == free_list_)
{
alloc();
}
auto* pAvailable = free_list_; // 할당해주는 블럭은 free 목록에서 제외
free_list_ = *reinterpret_cast<unsigned char**>(pAvailable); // 할당하는 메모리가 다음으로 가리키던 메모리 가리킴
++cur_use_count_;
return pAvailable;
}
static void operator delete(void* obj)
{
ScopeLock sl(&lock_);
--cur_use_count_;
*reinterpret_cast<unsigned char**>(obj) = free_list_; // 반환하는 메모리가 이전 free를 가리키고
free_list_ = static_cast<unsigned char*>(obj); // free를 반환하는 메모리로 설정
}
inline static int GetTotalCount() { return total_count_; }
inline static int GetUseCount() { return cur_use_count_; }
protected:
static void alloc()
{
free_list_ = new uchar[sizeof(T) * ALLOC_COUNT];
uchar* pNext = free_list_;
uchar** ppCurr = reinterpret_cast<uchar**>(free_list_);
for (int i = 0; i < ALLOC_COUNT; ++i)
{
assert(sizeof(T) > sizeof(void*), "T ptr size must be greater than void* size are small.");
pNext += sizeof(T);
*ppCurr = pNext; // 이전에 가리키던 블럭은 다음 블럭을 가리킨다
ppCurr = reinterpret_cast<uchar**>(pNext); // next가 또 움직여야 하니까 다음 블럭을 가리킨다.
}
*ppCurr = 0; ///< 마지막은 0으로 표시
total_count_ += ALLOC_COUNT;
}
private:
static Lock lock_;
static uchar* free_list_;
static int total_count_;
static int cur_use_count_;
};
template <typename T, size_t ALLOC_SIZE>
unsigned char* B2ObjectPool<T, ALLOC_SIZE>::free_list_ = nullptr;
template <typename T, size_t ALLOC_SIZE>
int B2ObjectPool<T, ALLOC_SIZE>::total_count_ = 0;
template <typename T, size_t ALLOC_SIZE>
int B2ObjectPool<T, ALLOC_SIZE>::cur_use_count_ = 0;
그치만 이젠 그럴 필요 있을까... 포인터 주소를 STL Queue 같은 컨테이너를 써서 관리하면 될거 같다.
320x100
'쿼리큘럼 개인적 정리' 카테고리의 다른 글
네트워크 장비 이해 (0) | 2021.10.05 |
---|---|
직렬화버퍼 (0) | 2021.10.05 |
게임의 길찾기 (0) | 2021.09.29 |
장르별 메시지 설계 (0) | 2021.09.29 |
프로토콜 설계 (0) | 2021.09.26 |