내가만든/라인들2016. 2. 28. 16:47

C/C++

메모리풀 포인터 구현 버전

메모리풀을 포인터와 벡터로 구현해 보았는데,

벡터는 너무 간단하여 포인터로 직접 구현한 뒤, 범용적으로 사용하기 위해 템플릿 적용.

메모리풀을 사용하면 할당하는데에 작은 시간비용이 추가 되긴 하지만,

leak방지와 메모리 관리에 효율 적이다.

자세한 내용은 SVN에 :)

template< class Type, int nSize >
class Pool
{
private:
 struct Node
 {
  Type clsItem;

  Node * pNext;
 };

public: 
 Pool();
 ~Pool(){}

 int GetPoolSize()
 { return this->m_nPoolSize; }

 int GetMaxCount()
 { return this->m_nMaxCount; }

 int GetUsedCount()
 { return this->m_nUsedCount; }
public:
 Type*    Capture();
 void    Release(); // Test
 void    Release( Type * pItem );

private:
 int m_nPoolSize; // 메모리 풀 사이즈
 int m_nUsedCount; // 사용 중인 객체 갯수
 int m_nMaxCount; // 메모리 풀에 보유중인 객체 전체 갯수

 Node * m_pVacant; // 사용 가능 객체 모음 포인터
 Node * m_pOccupied; // 사용 중인 객체 모음 포인터
};

template< class Type, int nSize >
Pool<Type, nSize>::Pool()
{
 m_nPoolSize  = sizeof(*this);
 m_nUsedCount = 0;
 m_nMaxCount  = 0;

 m_pVacant  = nullptr;
 m_pOccupied  = nullptr;
 
 for( int i = 0; i < nSize; i++ )
 {
  Node * pNewNode = new Node();

  m_nPoolSize += sizeof(Type); // 생성한 노드 만큼 풀 사이즈 증가
  m_nMaxCount += 1;    // 전체 객체 갯수 증가

  if( nullptr == m_pVacant )
  {   
   pNewNode->pNext = nullptr;
   m_pVacant = pNewNode;
   continue;
  }
  
  pNewNode->pNext = m_pVacant->pNext;
  m_pVacant->pNext = pNewNode;
 }
}

template< class Type, int nSize >
Type*
Pool<Type, nSize>::Capture()
{
 Node * pNode = m_pVacant;
 if( nullptr != pNode ) // 풀에 비어있는 노드가 있다면
 {
  m_pVacant = pNode->pNext;
 }
 else // 비어있는 노드가 없다면
 {
  pNode = new Node();

  m_nPoolSize += sizeof(Type);
  m_nMaxCount += 1;
 }
 
 // 사용중 객체 리스트에 넣는다
 pNode->pNext = m_pOccupied;
 m_pOccupied  = pNode;
  
 m_nUsedCount += 1;
 
 return &(pNode->clsItem);
}

template< class Type, int nSize >
void
Pool<Type, nSize>::Release() /* TEST (맨 앞 노드 해제) */
{
 if( nullptr == m_pOccupied )
 {
  return;
 }

 Node * pReleaseNode = m_pOccupied;
 m_pOccupied = pReleaseNode->pNext;

 // 미사용 객체 리스트에 넣는다
 pReleaseNode->pNext = m_pVacant;
 m_pVacant = pReleaseNode;
 
 m_nUsedCount -= 1;
}

template< class Type, int nSize >
void
Pool<Type, nSize>::Release( Type * pItem )
{
 if( nullptr == pItem )
 {
  return;
 }

 bool bIsExist = false;
 Node * pPrevNode = nullptr;
 Node * pCurNode = m_pOccupied;
 for( pCurNode; /* 사용중인 객체를 순회 한다 */
   nullptr != pCurNode;
   pCurNode = pCurNode->pNext )
 {
  if( pItem == &(pCurNode->clsItem) )
  {
   bIsExist = true;
  }
  pPrevNode = pCurNode;
 }

 if( false == bIsExist ) // 사용중인 객체가 없다
 {
  return;
 }

 // 노드가 존재하는데 이전의 노드가 null이라면, 첫번째 노드이다
 if( nullptr == pPrevNode )
 {
  m_pOccupied = pCurNode->pNext;
 }
 else
 {
  pPrevNode->pNext = pCurNode->pNext;
 }

 m_nUsedCount -= 1; // 사용중인 객체의 수를 감소 시킨다
 
 // 미사용 객체 리스트에 넣는다
 pCurNode->pNext = m_pVacant;
 m_pVacant = pCurNode;

 m_nUsedCount -= 1;
}

Posted by 비엔나햄