00001
00002
00003
00004
00005
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
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
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
00106
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
00137
00138
00139
00140
00141 t->~T();
00142 {
00143
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
00154
00155
00156
00157
00158 for( size_t i = 0; i < chunk.size(); i++ )
00159 chunk[i]->~T();
00160 {
00161
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_