Skip to content

Std::allocator:Pool

STL은 객체들을 관리할 수 있는 컨테이너 객체를 제공한다. 우리가 오브젝트 풀을 사용할때, STL의 도움을 받을 수 있다면 더 사용성이 높고 관리하기 편한 풀을 사용할 수 있을 것이다. STL은 일반적으로 새로운 객체를 받아서 저장할 때, 대상 객체를 복사해서 저장하고, 해제할때는 객체의 소멸자를 호출하는 방식으로 동작한다. 이 동작을 우리의 풀에 맞는 동작으로 변경할 수 있다면 STL에 풀을 적용하는 것이 꿈은 아닐 것이다. 하지만 STL내부 동작을 변경하려면 라이브러리를 건드려야할텐데, 뭔가 마음 한켠에서 '괜찮을까?'하는 울림이 전해져 온다. 이런 우리의 고민을 알아주기라도 하듯 STL은 객체를 받아서 할당하고 지울때 해제하는 동작을 커스터마이징 할 수 있는 API를 제공한다. 이것이 STL Custom Allocator이다.

STL Allocator 사용법

Custom Allocator를 구현하는데 있어 반드시 지켜야할 사항들이 있다.

  • CustomAllocator는 template으로 구현되어야 한다.
  • pointer, reference 타입을 typedef로 정의해야한다.
  • allocator는 멤버 변수를 가질 수 없다. (stateless functor)
  • rebind 템플릿이 필수적이다. 재할당이 필요한 경우 rebind를 allocator 대신 사용하기 때문인듯...

STL Allocator 예제 코드

메모리 풀 사용하는 Allocator Template:

//템플릿으로 작성할 것
template <class T>
class STLAllocator
{
public:
   STLAllocator() = default;

   //필요한 타입 정의들...
   typedef T value_type;
   typedef value_type* pointer;
   typedef const value_type* const_pointer;
   typedef value_type& reference;
   typedef const value_type& const_reference;
   typedef std::size_t size_type;
   typedef std::ptrdiff_t difference_type;

   //복사 생성자
   template <class U>
   STLAllocator(const STLAllocator<U>&)
   {}

   //rebind 템플릿
   template <class U>
   struct rebind
   {
      typedef STLAllocator<U> other;
   };

   void construct(pointer p, const T& t)
   {
      //replace new (할당하지 않고 생성자만 호출)
      new(p)T(t);
   }

   void destroy(pointer p)
   {
      //replace delete (해제하지 않고 소멸자만 호출)
      p->~T();
   }

   //할당시 호출되는 함수
   T* allocate(size_t n)
   {
      //메모리 풀에서 할당요청
      return GMemoryPool->Allocate(n);
   }
   //해제시 호출되는 함수
   void deallocate(T* ptr, size_t n)
   {
      //메모리풀에 반납요청
      GMemoryPool->Deallocate(ptr, n);
   }
};

Allocator STL에 적용하기:

//Allocator를 적용한 새로운 X-STL 
template <class T>
struct xvector
{
   typedef std::vector<T, STLAllocator<T>> type;
};

template <class T>
struct xdeque
{
   typedef std::deque<T, STLAllocator<T>> type;
};

template <class T>
struct xlist
{
   typedef std::list<T, STLAllocator<T>> type;
};

template <class K, class T, class C = std::less<K> >
struct xmap
{
   typedef std::map<K, T, C, STLAllocator<std::pair<K,T>>> type;
};

template <class T, class C = std::less<T> >
struct xset
{
   typedef std::set<T, C , STLAllocator<T>> type;
};

template <class K, class T, class C = std::hash_compare<K, std::less<K>> >
struct xhash_map
{
   typedef std::hash_map<K, T, C, STLAllocator<std::pair<K, T>> > type;
};

template <class T, class C = std::hash_compare<T, std::less<T>> >
struct xhash_set
{
   typedef std::hash_set<T, C, STLAllocator<T> > type;
};

template <class T, class C = std::less<std::vector<T>::value_type> >
struct xpriority_queue
{
   typedef std::priority_queue<T, std::vector<T, STLAllocator<T>>, C > type;
};

typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, STLAllocator<wchar_t>> xstring;


//실제 적용사례
//typedef ::type으로 X-STL의 타입을 받아 사용한다.
typedef xlist<ClientSession*>::type ClientList;
ClientList  mFreeSessionList;

See also

Favorite site