CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/DataFormats/GeometrySurface/src/BlockWipedAllocator.cc

Go to the documentation of this file.
00001 #include "DataFormats/GeometrySurface/interface/BlockWipedAllocator.h"
00002 #include "FWCore/Utilities/interface/Likely.h"
00003 
00004 BlockWipedAllocator::BlockWipedAllocator( std::size_t typeSize,
00005                                           std::size_t blockSize,
00006                                           std::size_t  maxRecycle):
00007   m_typeSize(typeSize), m_blockSize(blockSize), m_maxRecycle(maxRecycle), m_alive(0){
00008   //  if (typeSize<32) abort(); // throw std::bad_alloc();
00009   recycled.reserve(m_maxRecycle);
00010   wipe();
00011 }
00012   
00013 
00014 BlockWipedAllocator::BlockWipedAllocator(BlockWipedAllocator const & rh) :
00015   m_typeSize(rh.m_typeSize), m_blockSize(rh.m_blockSize), m_maxRecycle(rh.m_maxRecycle), m_alive(0) {
00016   recycled.reserve(m_maxRecycle);
00017   wipe();
00018 }
00019 
00020 BlockWipedAllocator& BlockWipedAllocator::operator=(BlockWipedAllocator const & rh) {
00021   m_typeSize=rh.m_typeSize; m_blockSize=rh.m_blockSize; m_maxRecycle=rh.m_maxRecycle;
00022   recycled.reserve(m_maxRecycle);
00023   m_alive=0;
00024   wipe();
00025   return *this;
00026 }
00027  
00028 
00029 BlockWipedAllocator::~BlockWipedAllocator() {
00030   clear();
00031 }
00032 
00033    
00034 // cannot keep the count as dealloc is never called...
00035 
00036 void * BlockWipedAllocator::alloc() {
00037   m_alive++;
00038   if likely(!recycled.empty()) {
00039     void * ret = recycled.back();
00040     recycled.pop_back();
00041     return ret;
00042   } 
00043   void * ret = m_next;
00044   m_next+=m_typeSize;
00045   Block & block = *m_current;
00046   ++block.m_allocated;
00047   if unlikely(m_next==(&block.m_data.back())+1) nextBlock(true);
00048   return ret;
00049 }
00050   
00051 void BlockWipedAllocator::dealloc(void * p) {
00052   if likely (recycled.size()<m_maxRecycle) recycled.push_back(p);
00053   m_alive--;
00054 }
00055 
00056 void BlockWipedAllocator::clear() const {
00057   me().m_blocks.clear();
00058   me().wipe();
00059 }
00060 
00061 void BlockWipedAllocator::wipe(bool force) const {
00062   if (m_alive>0 && !force) return;
00063   // reset caches
00064   std::for_each(localCaches.begin(),localCaches.end(),boost::bind(&LocalCache::reset,_1));
00065 
00066   me().m_current=me().m_blocks.begin();
00067   me().nextBlock(false);
00068   me().recycled.clear();
00069 }
00070   
00071 BlockWipedAllocator & BlockWipedAllocator::me() const {
00072   return const_cast<BlockWipedAllocator&>(*this);
00073 }
00074 
00075 BlockWipedAllocator::Stat BlockWipedAllocator::stat() const {
00076   Stat s = { m_typeSize, m_blockSize, (*m_current).m_allocated,
00077              (&*(*m_current).m_data.end()-m_next)/m_typeSize,
00078              std::distance(const_iterator(m_current),m_blocks.end()),
00079              m_blocks.size(), m_alive};
00080   return s;
00081 }
00082 
00083 void BlockWipedAllocator::nextBlock(bool advance) {
00084   if likely(advance) m_current++;
00085   if unlikely(m_current==m_blocks.end()) {
00086     m_blocks.push_back(Block());
00087     m_current=m_blocks.end(); --m_current;
00088   }
00089   m_current->m_data.resize(m_blockSize*m_typeSize);
00090   m_current->m_allocated=0;
00091   m_next = &(m_current->m_data.front());
00092 }
00093 
00094 
00095 BlockWipedPool::BlockWipedPool(std::size_t blockSize, std::size_t  maxRecycle) : 
00096   m_blockSize(blockSize),  m_maxRecycle(maxRecycle), m_last(0), m_lastSize(0){}
00097 
00098 BlockWipedPool::~BlockWipedPool() {clear();}
00099 
00100 
00101 
00102 BlockWipedPool::Allocator & BlockWipedPool::allocator( std::size_t typeSize) {
00103   if likely(m_lastSize==typeSize) return *m_last;
00104   Pool::iterator p=m_pool.find(typeSize);
00105   m_lastSize=typeSize;
00106   if likely (p!=m_pool.end())  return *(m_last = &(*p).second);
00107   return *(m_last=&(*m_pool.insert(std::make_pair(typeSize,Allocator(typeSize, m_blockSize, m_maxRecycle))).first).second);
00108 }
00109 
00110 void BlockWipedPool::wipe(bool force) {
00111   std::for_each(m_pool.begin(),m_pool.end(),boost::bind(&Allocator::wipe,
00112                                                         boost::bind(&Pool::value_type::second,_1),force
00113                                                         ));
00114 }
00115 
00116 void BlockWipedPool::clear() {
00117   std::for_each(m_pool.begin(),m_pool.end(),boost::bind(&Allocator::clear,
00118                                                         boost::bind(&Pool::value_type::second,_1)
00119                                                         ));
00120 }
00121 
00122 
00123 
00124 
00125 BlockWipedPool & blockWipedPool(BlockWipedPool * p) {
00126   static BlockWipedPool * local=0;
00127   if (p!=0) local=p;
00128   return *local;
00129 }
00130 
00131 
00132 int BlockWipedPoolAllocated::s_alive=0;
00133 bool BlockWipedPoolAllocated::s_usePool=false;
00134 
00135 void BlockWipedPoolAllocated::usePool() { 
00136   // throw id s_alive!=0???
00137   if (0==s_alive) s_usePool=true;
00138 }
00139 
00140 
00141 
00142 void * BlockWipedPoolAllocated::operator new(size_t s) {
00143   s_alive++;
00144   return (s_usePool) ? allocator(s).alloc() : ::operator new(s);
00145 }
00146 
00147 static void *  BlockWipedPoolAllocated::operator new(size_t s, void * p) {
00148   return p;
00149 }
00150 
00151 #include<typeinfo>
00152 #include<iostream>
00153 struct AQ {
00154   virtual ~AQ(){}
00155 };
00156 void BlockWipedPoolAllocated::operator delete(void * p, size_t s) {
00157   if (0==p) return;
00158   // if (s<100) std::cout << typeid(*(BlockWipedPoolAllocated*)(p)).name() << std::endl;
00159   s_alive--;
00160   (s_usePool) ? allocator(s).dealloc(p) : ::operator delete(p);
00161 
00162 }
00163 
00164 BlockWipedAllocator & BlockWipedPoolAllocated::allocator(size_t s) {
00165   return  blockWipedPool().allocator(s);
00166 }
00167 
00168 
00169 BlockWipedAllocator::Stat BlockWipedPoolAllocated::stat(size_t s) {
00170   return allocator(s).stat();
00171 }
00172   
00173 
00174 #include "DataFormats/GeometrySurface/interface/ReferenceCounted.h"
00175 int ReferenceCountedPoolAllocated::s_alive=0;
00176 int ReferenceCountedPoolAllocated::s_referenced=0;