Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2016
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.54 KB | None | 0 0
  1.  
  2. /*
  3.  * Класс пула для быстрого выделения памяти под объекты заданного типа
  4.  * TYPE сразу блоками по BLOCK элементов
  5.  */
  6.  
  7. template<typename TYPE, size_t BLOCK> class CC_Pool {
  8.  
  9.     public:
  10.  
  11.     class Block;
  12.  
  13.     class Wrapper {
  14.         public:
  15.         TYPE object;
  16.         Wrapper *next; // следующий репер в очереди свободные реперов в блоке
  17.         Block *block; // блок, которому принадлежит репер
  18.     };
  19.  
  20.     class Block {
  21.         public:
  22.         Wrapper wrappers[BLOCK];
  23.         Wrapper *first;
  24.         Block *next;
  25.         void init();
  26.         int wrapCount;
  27.     };
  28.  
  29.     static __thread Block* first; // Указатель на первый блок, к котором есть свободные репперы
  30.  
  31.     static TYPE *create();
  32.     static void remove(TYPE*);
  33.  
  34.     static __thread int blockCount;
  35.  
  36.     CC_Pool();
  37.    
  38. };
  39.  
  40. template<typename TYPE, size_t BLOCK> __thread typename CC_Pool<TYPE, BLOCK>::Block * CC_Pool<TYPE, BLOCK>::first = nullptr;
  41. template<typename TYPE, size_t BLOCK> __thread int CC_Pool<TYPE, BLOCK>::blockCount = 0;
  42.  
  43. template<typename TYPE, size_t BLOCK> CC_Pool<TYPE, BLOCK>::CC_Pool()
  44. {
  45.     blockCount = 0;
  46. }
  47.  
  48. template<typename TYPE, size_t BLOCK> inline TYPE* CC_Pool<TYPE, BLOCK>::create()
  49. {
  50.     if (first == nullptr) {
  51.         // нет свободных блоков, надо зарезервировать новый блок
  52.         first = (Block*) :: operator new (sizeof(Block));
  53.         first->init();
  54.         blockCount++;
  55.     }
  56.    
  57.     // в первом свободном блоке зарезервировать первый свободный элемент
  58.     Wrapper *wrapper = first->first;
  59.     first->first = first->first->next;
  60.     first->wrapCount--;
  61.    
  62.     // если блок при этом перестал быть свободным - убрать его из очереди
  63.     if (first->first == nullptr) {
  64.         first = first->next;
  65.     }
  66.    
  67.     // вернуть объект, заключенный в рэппере
  68.     return (TYPE*) &wrapper->object;
  69. }
  70.  
  71. template<typename TYPE, size_t BLOCK> inline void CC_Pool<TYPE, BLOCK>::remove(TYPE *object)
  72. {
  73.     // определить реппер по объеку
  74.     Wrapper *wrapper = (Wrapper*) object;
  75.    
  76.     // Этот реппер относится к блоку
  77.     Block *block = wrapper->block;
  78.    
  79.     if (block->first == nullptr) {
  80.         // если блок полный, то поставить его в очередь как пустой,
  81.         // поскольку в нем сейчас освободится один репер
  82.         block->next = first;
  83.         first = block;
  84.     }
  85.    
  86.     // поставить этот репер первым в очереди свободных реперов блока
  87.     wrapper->next = block->first;
  88.     block->first = wrapper;
  89.    
  90.     // если этот и следующий блоки совсем пустые, то удалить следующий
  91.     block->wrapCount++;
  92.     if (block->wrapCount == BLOCK && block->next != nullptr && block->next->wrapCount == BLOCK) {
  93.         Block *next = block->next;
  94.         block->next = block->next->next;
  95.         delete next;
  96.         blockCount--;
  97.     }
  98. }
  99.  
  100. template<typename TYPE, size_t BLOCK> void CC_Pool<TYPE, BLOCK>::Block::init()
  101. {
  102.     next = nullptr;
  103.     // все рэпперы в блоке надо поставить в очередь свободных
  104.     first = &wrappers[0];
  105.     for (int i = 0; i < BLOCK-1; i++) {
  106.         wrappers[i].next = &wrappers[i+1];
  107.         wrappers[i].block = this;
  108.     }
  109.     wrappers[BLOCK-1].next = nullptr;
  110.     wrappers[BLOCK-1].block = this;
  111.     wrapCount = BLOCK;
  112. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement