Go to the documentation of this file.00001 #ifndef BlockWipedAllocator_H
00002 #define BlockWipedAllocator_H
00003
00004 #include<vector>
00005 #include<list>
00006
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
00018
00019
00020
00021
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
00032
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
00045 void clear() const;
00046
00047
00048 void wipe(bool force=true) const;
00049
00050
00051
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;
00107
00108 };
00109
00110
00111 class BlockWipedPool {
00112 public:
00113 typedef BlockWipedAllocator Allocator;
00114
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
00145
00146
00147 class BlockWipedPoolAllocated {
00148 public:
00149 virtual ~BlockWipedPoolAllocated(){}
00150
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
00163 static void usePool();
00164
00165
00166
00167 static bool s_usePool;
00168
00169 };
00170
00171
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
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
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
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
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
00309 };
00310
00311
00312 #endif // BlockAllocator_H