Skip to content
Search

Std::allocator:Pool

lastmod 2018-08-17created 2016-12-012 edits

The STL provides container objects that can manage objects. When we use an object pool, if we can get help from the STL, we can use a pool that is more usable and easier to manage. When the STL receives and stores a new object, it generally copies the target object to store it, and when releasing, it calls the object's destructor. If we can change this behavior to match our pool, applying a pool to the STL is not just a dream. But changing the STL's internal behavior would mean touching the library, and somewhere in the back of your mind a voice asks, "Is this okay?" As if it understood our concern, the STL provides an API for customizing how it allocates objects it receives and frees them when they are removed. This is the STL Custom Allocator.

STL Allocator usage

There are requirements you must follow when implementing a Custom Allocator.

  • A CustomAllocator must be implemented as a template.
  • The pointer and reference types must be defined with typedef.
  • An allocator cannot have member variables. (stateless functor)
  • The rebind template is required. Probably because rebind is used instead of the allocator when reallocation is needed...

STL Allocator example code

Allocator Template using a memory pool:

//템플릿으로 작성할 것
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);
   }
};

Applying the Allocator to the 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