EvolvingObjects
node_pool.h
00001 
00018 #ifndef node_pool_h
00019 #define node_pool_h
00020 
00021 class MemPool
00022 {
00023 public :
00024 
00025     MemPool(unsigned int sz) : esize(sz<sizeof(Link)? sizeof(Link) : sz) {}
00026     ~MemPool()
00027     {
00028         Chunk* n = chunks;
00029         while(n)
00030         {
00031             Chunk* p = n;
00032             n = n->next;
00033             delete p;
00034         }
00035     }
00036 
00037     void* allocate()
00038     {
00039         if (head == 0) grow();
00040         Link* p = head;
00041         head = p->next;
00042         return static_cast<void*>(p);
00043     }
00044 
00045     void deallocate(void* b)
00046     {
00047         Link* p = static_cast<Link*>(b);
00048         p->next = head;
00049         head = p;
00050     }
00051 
00052 private :
00053 
00054     void grow()
00055     {
00056         Chunk* n = new Chunk;
00057         n->next = chunks;
00058         chunks = n;
00059 
00060         const int nelem = Chunk::size/esize;
00061         char* start = n->mem;
00062         char* last  = &start[(nelem-1)*esize];
00063         for (char* p = start; p < last; p += esize)
00064         {
00065             reinterpret_cast<Link*>(p)->next =
00066                 reinterpret_cast<Link*>(p + esize);
00067         }
00068 
00069         reinterpret_cast<Link*>(last)->next = 0;
00070         head = reinterpret_cast<Link*>(start);
00071     }
00072 
00073     struct Link
00074     {
00075         Link* next;
00076     };
00077 
00078     struct Chunk
00079     {
00080         enum {size = 8 * 1024 - 16};
00081         Chunk* next;
00082         char mem[size];
00083     };
00084 
00085     Chunk* chunks;
00086     const unsigned int esize;
00087     Link* head;
00088 };
00089 
00090 template<class T>
00091 class Node_alloc
00092 {
00093 public :
00094 
00095     T* allocate(void)
00096     {
00097         T* t = static_cast<T*>(mem.allocate());
00098         t = new  (t) T;
00099         return t;
00100     }
00101 
00102     T* construct(const T& org)
00103     {
00104         T* t = static_cast<T*>(mem.allocate());
00105         t = new  (t) T(org);
00106         return t;
00107     }
00108 
00109     void deallocate(T* t)
00110     {
00111         t->~T(); // call destructor
00112         mem.deallocate(static_cast<void*>(t));
00113     }
00114 
00115 private :
00116     static MemPool mem;
00117 };
00118 
00119 
00120 template <class T>
00121 class Standard_alloc
00122 {
00123 public :
00124     Standard_alloc() {}
00125 
00126     T* allocate(size_t arity = 1)
00127     {
00128         if (arity == 0)
00129             return 0;
00130 
00131         return new T [arity];
00132     }
00133 
00134     T* construct(size_t arity, T* org)
00135     {
00136         if (arity == 0)
00137             return 0;
00138 
00139         T* t = new T [arity];
00140 
00141         for (int i = 0; i < arity; ++i)
00142         {
00143             t = T(org[i]);
00144         }
00145     }
00146 
00147     void deallocate(T* t, size_t arity = 1)
00148     {
00149         if (arity == 0)
00150             return ;
00151 
00152         delete [] t;
00153     }
00154 
00155 };
00156 
00157 template <class T>
00158 class Standard_Node_alloc
00159 {
00160 public :
00161     Standard_Node_alloc() {}
00162 
00163     T* allocate(void)
00164     {
00165         return new T;// [arity];
00166     }
00167 
00168     T* construct(const T& org)
00169     {
00170         return new T(org);
00171     }
00172 
00173     void deallocate(T* t)
00174     {
00175         delete t;
00176     }
00177 
00178 };
00179 
00180 template <class T>
00181 class Tree_alloc
00182 {
00183 public :
00184     Tree_alloc() {}
00185 
00186     T* allocate(size_t arity)
00187     {
00188         T* t;
00189 
00190         switch(arity)
00191         {
00192 
00193         case 0 : return 0;
00194         case 1 :
00195             {
00196                 t = static_cast<T*>(mem1.allocate());
00197                 new (t) T;
00198                 break;
00199             }
00200         case 2 :
00201             {
00202                 t = static_cast<T*>(mem2.allocate());
00203                 new (t) T;
00204                 new (&t[1]) T;
00205                 break;
00206             }
00207         case 3 :
00208             {
00209                 t = static_cast<T*>(mem3.allocate());
00210                 new (t) T;
00211                 new (&t[1]) T;
00212                 new (&t[2]) T;
00213                 break;
00214             }
00215         default :
00216             {
00217                 return new T[arity];
00218             }
00219         }
00220 
00221         return t;
00222      }
00223 
00224     T* construct(size_t arity, T* org)
00225     {
00226         T* t;
00227 
00228         switch(arity)
00229         {
00230 
00231         case 0 : return 0;
00232         case 1 :
00233             {
00234                 t = static_cast<T*>(mem1.allocate());
00235                 new (t) T(*org);
00236                 break;
00237             }
00238         case 2 :
00239             {
00240                 t = static_cast<T*>(mem2.allocate());
00241                 new (t) T(*org);
00242                 new (&t[1]) T(org[1]);
00243                 break;
00244             }
00245         case 3 :
00246             {
00247                 t = static_cast<T*>(mem3.allocate());
00248                 new (t) T(*org);
00249                 new (&t[1]) T(org[1]);
00250                 new (&t[1]) T(org[2]);
00251                 break;
00252             }
00253         default :
00254             {
00255                 t = new T[arity]; // does call default ctor
00256                 for (int i = 0; i < arity; ++i)
00257                 {
00258                     t[i] = T(org[i]); // constructs now
00259                 }
00260             }
00261         }
00262 
00263         return t;
00264      }
00265 
00266 
00267 
00268     void deallocate(T* t, size_t arity)
00269     {
00270         switch(arity)
00271         {
00272         case 0: return;
00273         case 3 :
00274             {
00275                 t[2].~T(); t[1].~T(); t[0].~T();
00276                 mem3.deallocate(static_cast<void*>(t));
00277                 return;
00278             }
00279         case 2 :
00280             {
00281                 t[1].~T(); t[0].~T();
00282                 mem2.deallocate(static_cast<void*>(t));
00283                 return;
00284             }
00285         case 1 :
00286             {
00287                 t[0].~T();
00288                 mem1.deallocate(static_cast<void*>(t));
00289                 return;
00290             }
00291         default :
00292             {
00293                 delete [] t;
00294                 return;
00295             }
00296         }
00297     }
00298 
00299 
00300 private :
00301     static MemPool mem1;
00302     static MemPool mem2;
00303     static MemPool mem3;
00304 };
00305 
00306 // static (non thread_safe) memory pools
00307 template <class T> MemPool Node_alloc<T>::mem  = sizeof(T);
00308 
00309 template <class T> MemPool Tree_alloc<T>::mem1 = sizeof(T);
00310 template <class T> MemPool Tree_alloc<T>::mem2 = sizeof(T) * 2;
00311 template <class T> MemPool Tree_alloc<T>::mem3 = sizeof(T) * 3;
00312 
00313 #endif
 All Classes Namespaces Files Functions Variables Typedefs Friends