CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/DataFormats/GeometrySurface/interface/BlockWipedAllocator.h

Go to the documentation of this file.
00001 #ifndef BlockWipedAllocator_H
00002 #define BlockWipedAllocator_H
00003 
00004 #include<vector>
00005 #include<list>
00006 // #include<map>
00007 #include <ext/hash_map>
00008 
00009 #include <algorithm>
00010 #include<memory>
00011 
00012 #include<boost/bind.hpp>
00013 
00014 #include "FWCore/Utilities/interface/Visibility.h"
00015 
00016 
00017 // #include<iostream>
00018 
00019 /*  Allocator that never removes single allocations
00020  *  it "wipes" or "clears" the whole allocation when not needed anymore
00021  *  if not wiped it may easily run out of memory
00022  */
00023 class BlockWipedAllocator {
00024 public:
00025   BlockWipedAllocator( std::size_t typeSize,
00026                        std::size_t blockSize,
00027                        std::size_t  maxRecycle
00028                        );
00029   
00030 
00031   /*  copy constructor clone the allocator and the memory it manages
00032    *  it needs to be reinitialized to avoid pointing to "rh"
00033    *
00034    */
00035   BlockWipedAllocator(BlockWipedAllocator const & rh);
00036 
00037   BlockWipedAllocator& operator=(BlockWipedAllocator const & rh);
00038   ~BlockWipedAllocator();
00039 
00040   void * alloc();
00041  
00042   void dealloc(void *);
00043 
00044   // redime memory to the system heap
00045   void clear() const;
00046 
00047   // reset allocator status. does not redime memory
00048   void wipe(bool force=true) const;
00049 
00050 
00051   // longliving (static) local caches: to be reset at wipe
00052   struct LocalCache {
00053     virtual ~LocalCache(){}
00054     virtual void reset()=0;
00055   };
00056 
00057   void registerCache(LocalCache * c) {
00058     localCaches.push_back(c);
00059   }
00060 
00061 private:
00062   std::vector<LocalCache*> localCaches;
00063   std::vector<void *> recycled;
00064 
00065 
00066 protected:
00067 
00068   BlockWipedAllocator & me() const;
00069 
00070 public:
00071 
00072   struct Stat {
00073     size_t typeSize;
00074     size_t blockSize;
00075     size_t currentOccupancy;
00076     size_t currentAvailable;
00077     std::ptrdiff_t totalAvailable;
00078     size_t nBlocks;
00079     int alive;
00080   };
00081   
00082   Stat stat() const;
00083   
00084 private:
00085   void nextBlock(bool advance) dso_internal;
00086 
00087 
00088   struct Block {
00089     std::size_t m_allocated;
00090     std::vector<unsigned char> m_data;
00091   };
00092 
00093   typedef unsigned char * pointer; 
00094   typedef std::list<Block> Blocks;
00095   typedef Blocks::iterator iterator;
00096   typedef Blocks::const_iterator const_iterator;
00097 
00098 
00099   std::size_t m_typeSize;
00100   std::size_t m_blockSize;
00101   std::size_t m_maxRecycle;
00102   pointer m_next;
00103   iterator m_current;
00104   Blocks m_blocks;
00105 
00106   int m_alive; // for stat purposes
00107 
00108 };
00109 
00110 
00111 class BlockWipedPool {
00112 public:
00113   typedef BlockWipedAllocator Allocator;
00114   //  typedef std::map<std::size_t, Allocator> Pool;
00115   typedef __gnu_cxx::hash_map<std::size_t, Allocator> Pool;
00116 
00117   BlockWipedPool(std::size_t blockSize, std::size_t  maxRecycle);
00118   ~BlockWipedPool();
00119 
00120   Allocator & allocator( std::size_t typeSize);
00121 
00122   void wipe(bool force=true);
00123 
00124   void clear();
00125 
00126   template<typename Visitor>
00127   void visit(Visitor& visitor) const {
00128     std::for_each(m_pool.begin(),m_pool.end(),boost::bind(&Visitor::visit,visitor,
00129                                                           boost::bind(&Pool::value_type::second,_1)
00130                                                           ));
00131   }
00132 
00133 
00134 private:
00135   std::size_t m_blockSize;
00136   std::size_t m_maxRecycle;
00137   Pool m_pool;
00138   Allocator * m_last;
00139   std::size_t m_lastSize;
00140 };
00141 
00142 
00143 
00144 /*  generaric Basic class
00145  * 
00146  */
00147 class BlockWipedPoolAllocated {
00148 public:
00149   virtual ~BlockWipedPoolAllocated(){}
00150   // instance counter...
00151   static int s_alive;
00152   static void * operator new(size_t s, void * p);
00153   static void * operator new(size_t s);
00154   
00155   static void operator delete(void * p, size_t s);
00156   
00157   static BlockWipedAllocator & allocator(size_t s);
00158   
00159 
00160   static BlockWipedAllocator::Stat stat(size_t s);
00161   
00162   // throw id s_alive!=0???
00163   static void usePool();
00164 
00165 
00166   // private:
00167   static bool s_usePool;
00168   // static BlockAllocator * s_allocator;
00169 };
00170 
00171 // singleton
00172 BlockWipedPool & blockWipedPool(BlockWipedPool * p=0);
00173 
00174 template<size_t S>
00175 BlockWipedAllocator & blockWipedAllocator() {
00176   static BlockWipedAllocator & local = blockWipedPool().allocator(S);
00177   return local;
00178 }
00179 
00180 template<typename T>
00181 struct LocalCache : public BlockWipedAllocator::LocalCache {
00182   std::auto_ptr<T> ptr;
00183   LocalCache(){ 
00184     if (BlockWipedPoolAllocated::s_usePool)
00185       blockWipedAllocator<sizeof(T)>().registerCache(this);
00186   }
00187   ~LocalCache(){}
00188   void reset(){ ptr.reset();}
00189 };
00190 
00191 
00192 /*  Allocator by type
00193  * 
00194  */
00195 template<typename T>
00196 class BlockWipedAllocated {
00197 public:
00198   static void * operator new(size_t) {
00199     return alloc();
00200   }
00201   
00202   static void operator delete(void * p) {
00203     dealloc(p);
00204   }
00205   
00206   static void * operator new(size_t, void * p) {
00207     return p;
00208   }
00209 
00210   static void * alloc() {
00211     BlockWipedPoolAllocated::s_alive++;
00212     return (BlockWipedPoolAllocated::s_usePool) ? allocator().alloc()  : ::operator new(sizeof(T));
00213   }
00214   
00215   static void dealloc(void * p) {
00216     if (0==p) return;
00217     BlockWipedPoolAllocated::s_alive--;
00218     return (BlockWipedPoolAllocated::s_usePool) ? allocator().dealloc(p)  : ::operator delete(p);
00219   }
00220   
00221 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00222   template<typename... Args>
00223   static void
00224   construct(T *  p, Args&&... args)
00225       { ::new(p) T(std::forward<Args>(args)...); }
00226 #endif
00227 
00228 
00229   static void destroy( T * p) {  p->~T(); }
00230 
00231 
00232   static BlockWipedAllocator & allocator() {
00233     static BlockWipedAllocator & local = blockWipedPool().allocator(sizeof(T));
00234     return local;
00235   }
00236   
00237 
00238   static BlockWipedAllocator::Stat stat() {
00239     return allocator().stat();
00240   }
00241   
00242 
00243 private:
00244   
00245   // static BlockAllocator * s_allocator;
00246 };
00247 
00248 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00249 template<typename B>
00250 struct BWADestroy {
00251     BWADestroy() {}
00252     void operator () (B* p) { 
00253       if (0==p) return;
00254       BlockWipedPoolAllocated::s_alive--;
00255       if (BlockWipedPoolAllocated::s_usePool) {
00256         BlockWipedAllocator & local =  blockWipedPool().allocator(p->size());
00257         p->~B();
00258         local.dealloc(p);
00259       }
00260       else { delete p; }
00261     }
00262   };
00263 
00264 template<typename B>
00265 struct BWAFactory {
00266   typedef  BWADestroy<B> Destroy;
00267   typedef std::unique_ptr<B,  BWAFactory<B>::Destroy> UP;
00268   template<typename T, typename... Args>
00269   static UP create(Args&&... args) {
00270     // create derived, destroy base
00271     UP ret( (T*)BlockWipedAllocated<T>::alloc(),
00272             Destroy()
00273             );
00274     BlockWipedAllocated<T>::construct((T*)ret.get(),std::forward<Args>(args)...);
00275     return ret;
00276   }
00277 };
00278 #endif
00279 
00280 
00281 
00282 /*  Allocator by size (w/o pool)
00283  * 
00284  */
00285 template<typename T>
00286 class SizeBlockWipedAllocated {
00287 public:
00288   static void * operator new(size_t) {
00289     return allocator().alloc();
00290   }
00291   
00292   static void operator delete(void * p) {
00293     allocator().dealloc(p);
00294   }
00295   
00296   static BlockWipedAllocator & allocator() {
00297     static BlockWipedAllocator & local = blockWipedAllocator<sizeof(T)>();
00298     return  local;
00299   }
00300   
00301 
00302   static BlockWipedAllocator::Stat stat() {
00303     return allocator().stat();
00304   }
00305   
00306 private:
00307   
00308   // static BlockAllocator * s_allocator;
00309 };
00310 
00311 
00312 #endif // BlockAllocator_H