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();
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
00030 void * BlockWipedAllocator::alloc() {
00031 m_alive++;
00032 if likely(!recycled.empty()) {
00033 void * ret = recycled.back();
00034 recycled.pop_back();
00035 return ret;
00036 }
00037 void * ret = m_next;
00038 m_next+=m_typeSize;
00039 Block & block = *m_current;
00040 ++block.m_allocated;
00041 if unlikely(m_next==(&block.m_data.back())+1) nextBlock(true);
00042 return ret;
00043 }
00044
00045 void BlockWipedAllocator::dealloc(void * p) {
00046 if likely (recycled.size()<m_maxRecycle) recycled.push_back(p);
00047 m_alive--;
00048 }
00049
00050 void BlockWipedAllocator::clear() const {
00051 me().m_blocks.clear();
00052 me().wipe();
00053 }
00054
00055 void BlockWipedAllocator::wipe(bool force) const {
00056 if (m_alive>0 && !force) return;
00057
00058 std::for_each(localCaches.begin(),localCaches.end(),boost::bind(&LocalCache::reset,_1));
00059
00060 me().m_current=me().m_blocks.begin();
00061 me().nextBlock(false);
00062 me().recycled.clear();
00063 }
00064
00065 BlockWipedAllocator & BlockWipedAllocator::me() const {
00066 return const_cast<BlockWipedAllocator&>(*this);
00067 }
00068
00069 BlockWipedAllocator::Stat BlockWipedAllocator::stat() const {
00070 Stat s = { m_typeSize, m_blockSize, (*m_current).m_allocated,
00071 (&*(*m_current).m_data.end()-m_next)/m_typeSize,
00072 std::distance(const_iterator(m_current),m_blocks.end()),
00073 m_blocks.size(), m_alive};
00074 return s;
00075 }
00076
00077 void BlockWipedAllocator::nextBlock(bool advance) {
00078 if likely(advance) m_current++;
00079 if unlikely(m_current==m_blocks.end()) {
00080 m_blocks.push_back(Block());
00081 m_current=m_blocks.end(); --m_current;
00082 }
00083 m_current->m_data.resize(m_blockSize*m_typeSize);
00084 m_current->m_allocated=0;
00085 m_next = &(m_current->m_data.front());
00086 }
00087
00088
00089 BlockWipedPool::BlockWipedPool(std::size_t blockSize, std::size_t maxRecycle) :
00090 m_blockSize(blockSize), m_maxRecycle(maxRecycle), m_last(0), m_lastSize(0){}
00091
00092
00093 BlockWipedPool::Allocator & BlockWipedPool::allocator( std::size_t typeSize) {
00094 if likely(m_lastSize==typeSize) return *m_last;
00095 Pool::iterator p=m_pool.find(typeSize);
00096 m_lastSize=typeSize;
00097 if likely (p!=m_pool.end()) return *(m_last = &(*p).second);
00098 return *(m_last=&(*m_pool.insert(std::make_pair(typeSize,Allocator(typeSize, m_blockSize, m_maxRecycle))).first).second);
00099 }
00100
00101 void BlockWipedPool::wipe(bool force) {
00102 std::for_each(m_pool.begin(),m_pool.end(),boost::bind(&Allocator::wipe,
00103 boost::bind(&Pool::value_type::second,_1),force
00104 ));
00105 }
00106
00107 void BlockWipedPool::clear() {
00108 std::for_each(m_pool.begin(),m_pool.end(),boost::bind(&Allocator::clear,
00109 boost::bind(&Pool::value_type::second,_1)
00110 ));
00111 }
00112
00113
00114
00115
00116 BlockWipedPool & blockWipedPool(BlockWipedPool * p) {
00117 static BlockWipedPool * local=0;
00118 if (p!=0) local=p;
00119 return *local;
00120 }
00121
00122
00123 int BlockWipedPoolAllocated::s_alive=0;
00124 bool BlockWipedPoolAllocated::s_usePool=false;
00125
00126 void BlockWipedPoolAllocated::usePool() {
00127
00128 if (0==s_alive) s_usePool=true;
00129 }
00130
00131
00132
00133 void * BlockWipedPoolAllocated::operator new(size_t s) {
00134 s_alive++;
00135 return (s_usePool) ? allocator(s).alloc() : ::operator new(s);
00136 }
00137
00138 static void * BlockWipedPoolAllocated::operator new(size_t s, void * p) {
00139 return p;
00140 }
00141
00142 #include<typeinfo>
00143 #include<iostream>
00144 struct AQ {
00145 virtual ~AQ(){}
00146 };
00147 void BlockWipedPoolAllocated::operator delete(void * p, size_t s) {
00148 if (0==p) return;
00149
00150 s_alive--;
00151 (s_usePool) ? allocator(s).dealloc(p) : ::operator delete(p);
00152
00153 }
00154
00155 BlockWipedAllocator & BlockWipedPoolAllocated::allocator(size_t s) {
00156 return blockWipedPool().allocator(s);
00157 }
00158
00159
00160 BlockWipedAllocator::Stat BlockWipedPoolAllocated::stat(size_t s) {
00161 return allocator(s).stat();
00162 }
00163
00164
00165 #include "DataFormats/GeometrySurface/interface/ReferenceCounted.h"
00166 int ReferenceCountedPoolAllocated::s_alive=0;
00167 int ReferenceCountedPoolAllocated::s_referenced=0;