메모리 폴
http://rakeion.blog.me/120124615590
메모리풀이란
공간을 미리 할당하고,
메모리 할당 요청시(new) 미리 할당된 공간의 포인터를 반환하는 방법이다.
아래는 new요청시, 메모리풀의 메모리 모습변화이다.
- 빨간화살표: 가용한 메모리 공간을 가르키는 포인터
- 남색 블록3개: 메모리 Page
- 남색 블록1개: 메모리 블록
- 초록색 블록: 다음 블록에 대한 Next 포인터
아래 흐름처럼, New 요청시,
현재 free 포인터를 반환하고,
Free 포인터값은 초록색 NEXT포인터값으로 할당한다.
반대로, delete요청시,
delete요청된 블록의 Next포인터를 현재 Free포인터값으로 지정하고,
Free 포인터는 delete 요청된 블록주소로 바꾼다.
잘 관찰해보자.
Free포인터가 지정하고 있는 블록공간을 이으면,
바로 SLL( Single Linked List)가 된다.
그리고 이 SLL은 모두 가용한 공간들이다.
정리하면, 메모리풀은
- 가용한 공간들을 링크드리스트로 묶어서 관리한다.
- 그 가용공간이 바닥나면, 빈 링크드 리스트를 덧붙이는 방식으로 공간을 늘린다.
( Add List to the Tail) - 공간을 해제하면, 그 공간을 링크드리스트 맨 앞쪽에 INSERT한다.
(Add Node to the Head)
#pragma once
#include <CASSERT>
#include <CSTDLIB>
template< class TCls, int ALLOC_SIZE =10>
class cMemPool
{
public:
static void* operator new( size_t in_alloc_size)
{
// Check
assert( in_alloc_size == sizeof(TCls));
assert( in_alloc_size >= sizeof(TCls*));
// Check: 공간할당이 안되어 있거나, 공간이 부족하면 재할당
if( s_pFree ==NULL)
{
s_pFree =(TCls*)malloc( sizeof(TCls)* ALLOC_SIZE);
// 블록 간에 링크드 리스트를 만든다.( 나중에 해제시 사용가능한 놈들만 링크)
TCls** pCur =reinterpret_cast<TCls**>(s_pFree);
for( int i =0; i <ALLOC_SIZE -1; i++)
{
pCur[i] =s_pFree +i +1;
}
pCur[ ALLOC_SIZE -1] =NULL;
}
// Last
TCls* ret =s_pFree;
s_pFree =* reinterpret_cast<TCls**>( s_pFree);
s_block_cnt++;
return ret;
}
static void operator delete( void* pDel)
{
// Check
if( s_block_cnt ==0) throw "delete error";
// Exec: 삭제할 공간과 Free한 공간 연결
TCls** pCur =reinterpret_cast<TCls**>( &pDel);
*pCur =s_pFree;
s_pFree =*pCur;
// Last
s_block_cnt--;
}
public:
cMemPool() {}
virtual ~cMemPool() {}
private:
static TCls* s_pFree;
static int s_block_cnt;
};
template< class TCls, int ALLOC_SIZE>
TCls* cMemPool<TCls>::s_pFree =NULL;
template< class TCls, int ALLOC_SIZE>
int cMemPool<TCls>::s_block_cnt =0;