libMems/SlotAllocator.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * $Id: SlotAllocator.h,v 1.6 2004/02/27 23:08:55 darling Exp $
00003  * This file is copyright 2002-2007 Aaron Darling and authors listed in the AUTHORS file.
00004  * This file is licensed under the GPL.
00005  * Please see the file called COPYING for licensing details.
00006  * **************
00007  ******************************************************************************/
00008 
00009 #ifndef _SlotAllocator_h_
00010 #define _SlotAllocator_h_
00011 
00012 #ifdef HAVE_CONFIG_H
00013 #include "config.h"
00014 #endif
00015 
00016 #include <vector>
00017 #include <list>
00018 #include <stdexcept>
00019 #include <iostream>
00020 #include "libMUSCLE/threadstorage.h"
00021 
00022 
00023 namespace mems {
00024 
00025 
00027 const double POOL_GROWTH_RATE = 1.6;
00028         
00038 template< class T >
00039 class SlotAllocator {
00040 public:
00041         static SlotAllocator<T>& GetSlotAllocator();
00042         T* Allocate();
00043         void Free( T* t );
00044         void Free( std::vector<T*>& chunk );
00045         ~SlotAllocator(){ 
00046                 Purge();
00047         };
00048         void Purge(){
00049 //#pragma omp critical
00050 //{
00051         std::vector<T*>& data = this->data.get();
00052         unsigned& tail_free = this->tail_free.get();
00053         unsigned& n_elems = this->n_elems.get();
00054         std::vector< T* >& free_list = this->free_list.get();
00055                 for( unsigned dataI = 0; dataI < data.size(); dataI++ )
00056                         free(data[dataI]);
00057                 data.clear();
00058                 free_list.clear();
00059                 tail_free = 0;
00060                 n_elems = 0;
00061 //}
00062         }
00063 
00064 protected:
00065         TLS< std::vector<T*> > data;
00066         TLS< unsigned > tail_free;
00067         TLS< unsigned > n_elems;        
00069         TLS< std::vector< T* > > free_list;
00070 
00071 private:
00072         SlotAllocator() : tail_free(0), n_elems(0) {};
00073         SlotAllocator& operator=( SlotAllocator& sa ){ n_elems = sa.n_elems; data = sa.data; tail_free = sa.tail_free; return *this;};
00074         SlotAllocator( SlotAllocator& sa ){ *this = sa; };
00075                 
00076 };
00077 
00078 template< class T >
00079 inline
00080 SlotAllocator< T >& SlotAllocator< T >::GetSlotAllocator(){
00081         static SlotAllocator< T >* sa = new SlotAllocator< T >();
00082         return *sa;
00083 }
00084 
00085 
00086 template< class T >
00087 inline
00088 T* SlotAllocator< T >::Allocate(){
00089         T* t_ptr = NULL;
00090 
00091 {
00092         std::vector<T*>& data = this->data.get();
00093         unsigned& tail_free = this->tail_free.get();
00094         unsigned& n_elems = this->n_elems.get();
00095         std::vector< T* >& free_list = this->free_list.get();
00096 //      omp_guard rex( locker );
00097         if( free_list.begin() != free_list.end() ){
00098                 t_ptr = free_list.back();
00099                 free_list.pop_back();
00100         }else if( tail_free > 0 ){
00101                 int T_index = n_elems - tail_free--;
00102                 t_ptr = &(data.back()[ T_index ]);
00103         }else{
00104 
00105                 // Last resort:
00106                 // increase the size of the data array
00107                 unsigned new_size = (unsigned)(n_elems * POOL_GROWTH_RATE);
00108                 if( new_size == 0 )
00109                         new_size++;
00110                 T* new_data = NULL;
00111                 while( true ){
00112                         try{
00113                                 new_data = (T*)malloc(sizeof(T)*new_size);
00114                                 break;
00115                         }catch(...){
00116                                 new_size = new_size / 2;
00117                                 if( new_size == 0 )
00118                                         break;
00119                         }
00120                 }
00121                 if( new_data == NULL || new_size == 0 ){
00122                         throw std::out_of_range( "SlotAllocator::Allocate(): Unable to allocate more memory" );
00123                 }
00124                 data.push_back( new_data );
00125                 tail_free = new_size - 1;
00126                 t_ptr = & data.back()[0];
00127                 n_elems = new_size;
00128         }
00129 }
00130         return t_ptr;
00131 }
00132 
00133 template< class T >
00134 inline
00135 void SlotAllocator< T >::Free( T* t ){
00136         // for debugging double free
00137 /*      for(size_t i = 0; i < free_list.size(); i++ )
00138                 if( free_list[i] == t )
00139                         std::cerr << "ERROR DOUBLE FREE\n";
00140 */      
00141         t->~T();
00142 {
00143 //      omp_guard rex( locker );
00144         std::vector< T* >& free_list = this->free_list.get();
00145 
00146         free_list.push_back( t );
00147 }
00148 }
00149 
00150 template< class T >
00151 inline
00152 void SlotAllocator< T >::Free( std::vector<T*>& chunk ){
00153         // for debugging double free
00154 /*      for(size_t i = 0; i < free_list.size(); i++ )
00155                 if( free_list[i] == t )
00156                         std::cerr << "ERROR DOUBLE FREE\n";
00157 */      
00158         for( size_t i = 0; i < chunk.size(); i++ )
00159                 chunk[i]->~T();
00160 {
00161 //      omp_guard rex( locker );
00162         std::vector< T* >& free_list = this->free_list.get();
00163         free_list.insert(free_list.end(), chunk.begin(), chunk.end());
00164 }
00165         chunk.clear();
00166 }
00167 
00168 }
00169 
00170 #endif  // _SlotAllocator_h_

Generated on Fri Mar 14 06:01:04 2008 for libMems by doxygen 1.3.6