CMS 3D CMS Logo

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