320x100
template <typename T, size_t ALLOC_COUNT>
class CObjectPool
{
using uchar = unsigned char;
public:
CObjectPool()
{
alloc();
}
~CObjectPool()
{
}
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 - 1; ++i)
{
// T의 크기가 반드시 포인터 크기보다 커야 한다
assert(sizeof(T) > sizeof(void*));
pNext += sizeof(T);
// 이전에 가리키던 블럭은 다음 블럭을 가리킨다
*ppCurr = pNext;
// next가 또 움직여야 하니까 다음 블럭을 가리킨다.
ppCurr = reinterpret_cast<uchar**>(pNext);
}
}
void* operator new(size_t size)
{
// lock
if (nullptr == free_list_)
{
alloc();
}
// 할당해주는 블럭은 free 목록에서 제외
auto* pAvailable = free_list_;
// 할당하는 메모리가 다음으로 가리키던 메모리 가리킴
free_list_ = *reinterpret_cast<unsigned char**>(pAvailable);
++cur_use_count_;
return pAvailable;
}
void operator delete(void* obj)
{
// lock
// cur_use_count_ <= 0 = error
--cur_use_count_;
// 반환하는 메모리가 이전 free를 가리키고
*reinterpret_cast<unsigned char**>(obj) = free_list_;
// free를 반환하는 메모리로 설정
free_list_ = static_cast<unsigned char*>(obj);
}
private:
uchar* free_list_;
int total_count_;
int cur_use_count_;
};
template <typename T, size_t ALLOC_SIZE>
unsigned char* CObjectPool<T, ALLOC_SIZE>::free_list_ = nullptr;
template <typename T, size_t ALLOC_SIZE>
int CObjectPool<T, ALLOC_SIZE>::total_count_ = 0;
template <typename T, size_t ALLOC_SIZE>
int CObjectPool<T, ALLOC_SIZE>::cur_use_count_ = 0;
결론적으로 첫 new가 실행되면 처음 설정했던 개수만큼 메모리를 할당하고, 각 메모리 크기의 블럭(?)이 링크드 리스트처럼 줄지어 대기한다.
그래서 header(=free_list)가 가리키는 메모리가 전달되고, 반환되면 해당 부분이 header가 된다.
여러 클래스에 맞게 사용할 수 있도록 템플릿으로 작성됨
320x100
'프로그래밍 > C,C++' 카테고리의 다른 글
자주 사용하는 함수 (0) | 2021.07.30 |
---|---|
[C++] 동적 배열을 이용한 stack (0) | 2021.06.30 |
RTTI란? (0) | 2021.06.18 |
비동기 함수 정리 (0) | 2021.03.22 |
가상 메모리 및 Large Address Aware (0) | 2020.02.19 |