00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #ifndef BLOCK_ALLOC_H
00053 #define BLOCK_ALLOC_H
00054
00055
00056 #include "dynarray.h"
00057 #include "mem_block.h"
00058
00059
00060 #include <new>
00061 #include <w.h>
00062 #include <stdlib.h>
00063 #include <deque>
00064
00065
00066
00067 template<class T, size_t MaxBytes>
00068 class block_alloc;
00069
00070 template<class T, size_t MaxBytes>
00071 inline
00072 void* operator new(size_t nbytes, block_alloc<T, MaxBytes> &alloc);
00073
00074 template<class T, size_t MaxBytes>
00075 inline
00076 void operator delete(void* ptr, block_alloc<T, MaxBytes> &alloc);
00077
00078
00079 struct dynpool : memory_block::block_pool {
00080 typedef memory_block::block mblock;
00081 pthread_mutex_t _lock;
00082 dynarray _arr;
00083 std::deque<mblock*> _free_list;
00084 size_t _chip_size;
00085 size_t _chip_count;
00086 size_t _log2_block_size;
00087 size_t _arr_end;
00088
00089 NORET dynpool(size_t chip_size, size_t chip_count,
00090 size_t log2_block_size, size_t max_bytes);
00091
00092 virtual
00093 NORET ~dynpool();
00094
00095 virtual
00096 bool validate_pointer(void* ptr);
00097
00098 protected:
00099
00100 size_t _size() const;
00101
00102 mblock* _at(size_t i);
00103
00104 virtual
00105 mblock* _acquire_block();
00106
00107 virtual
00108 void _release_block(mblock* b);
00109
00110 };
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 template<class T, class Pool=dynpool, size_t MaxBytes=0>
00154 struct block_pool
00155 {
00156 typedef memory_block::meta_block_size<sizeof(T)> BlockSize;
00157
00158
00159 static size_t block_size() { return BlockSize::BYTES; }
00160 static size_t chip_count() { return BlockSize::COUNT; }
00161 static size_t chip_size() { return sizeof(T); }
00162
00163
00164 #define TEMPLATE_ARGS chip_size(), chip_count(), block_size()
00165
00166 static Pool* get_pool() {
00167 static Pool p(chip_size(), chip_count(), BlockSize::LOG2,
00168 MaxBytes? MaxBytes : 1024*1024*1024);
00169 return &p;
00170 }
00171
00172 block_pool()
00173 : _blist(get_pool(), TEMPLATE_ARGS)
00174 {
00175 }
00176
00177
00178
00179 void* acquire() {
00180 return _blist.acquire(TEMPLATE_ARGS);
00181 }
00182
00183
00184
00185
00186
00187 static
00188 void release(void* ptr) {
00189 assert(get_pool()->validate_pointer(ptr));
00190 memory_block::block::release(ptr, TEMPLATE_ARGS);
00191 }
00192
00193 private:
00194 memory_block::block_list _blist;
00195
00196 };
00197
00198 template<class T, size_t MaxBytes=0>
00199 struct block_alloc {
00200
00201 typedef block_pool<T, dynpool, MaxBytes> Pool;
00202
00203 static
00204 void destroy_object(T* ptr) {
00205 ptr->~T();
00206 Pool::release(ptr);
00207 }
00208
00209 private:
00210 Pool _pool;
00211
00212
00213 friend void* operator new<>(size_t, block_alloc<T,MaxBytes> &);
00214 friend void operator delete<>(void*, block_alloc<T,MaxBytes> &);
00215 };
00216
00217 template<class T, size_t MaxBytes>
00218 inline
00219 void* operator new(size_t nbytes, block_alloc<T,MaxBytes> &alloc)
00220 {
00221 (void) nbytes;
00222 w_assert1(nbytes == sizeof(T));
00223 return alloc._pool.acquire();
00224 }
00225
00226
00227
00228
00229
00230 template<class T, size_t MaxBytes>
00231 inline
00232 void operator delete(void* ptr, block_alloc<T,MaxBytes> &alloc)
00233 {
00234 block_alloc<T,MaxBytes>::Pool::release(ptr);
00235 w_assert2(0);
00236 }
00237
00238 inline
00239 size_t dynpool::_size() const {
00240 return _arr_end >> _log2_block_size;
00241 }
00242
00243 inline
00244 dynpool::mblock* dynpool::_at(size_t i) {
00245 size_t offset = i << _log2_block_size;
00246 union { char* c; mblock* b; } u = {_arr+offset};
00247 return u.b;
00248 }
00249
00250
00251
00252 #undef TEMPLATE_ARGS
00253
00254
00255 template<class T>
00256 struct object_cache_default_factory {
00257
00258 static T*
00259 construct(void* ptr) { return new (ptr) T; }
00260
00261 static void
00262 reset(T* t) { }
00263
00264 static T*
00265 init(T* t) { return t; }
00266 };
00267
00268 template<class T>
00269 struct object_cache_initializing_factory {
00270
00271 static T*
00272 construct(void* ptr) { return new (ptr) T; }
00273
00274 static void
00275 reset(T* t) { t->reset(); }
00276
00277 static T*
00278 init(T* t) { t->init(); return t; }
00279
00280
00281 template<class Arg1>
00282 static T* init(T* t, Arg1 arg1) { t->init(arg1); return t; }
00283 template<class Arg1, class Arg2>
00284 static T* init(T* t, Arg1 arg1, Arg2 arg2) { t->init(arg1, arg2); return t; }
00285 template<class Arg1, class Arg2, class Arg3>
00286 static T* init(T* t, Arg1 arg1, Arg2 arg2, Arg3 arg3) { t->init(arg1, arg2, arg3); return t; }
00287 };
00288
00289 template <class T, class TFactory=object_cache_default_factory<T>, size_t MaxBytes=0>
00290 struct object_cache {
00291
00292
00293 T* acquire() {
00294 return TFactory::init(_acquire());
00295 }
00296 template<class Arg1>
00297 T* acquire(Arg1 arg1) {
00298 return TFactory::init(_acquire(), arg1);
00299 }
00300 template<class Arg1, class Arg2>
00301 T* acquire(Arg1 arg1, Arg2 arg2) {
00302 return TFactory::init(_acquire(), arg1, arg2);
00303 }
00304 template<class Arg1, class Arg2, class Arg3>
00305 T* acquire(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
00306 return TFactory::init(_acquire(), arg1, arg2, arg3);
00307 }
00308
00309 T* _acquire() {
00310
00311 union { void* v; T* t; } u = {_pool.acquire()};
00312 return u.t;
00313 }
00314
00315 static
00316 void release(T* obj) {
00317 TFactory::reset(obj);
00318 Pool::release(obj);
00319 }
00320
00321 private:
00322
00323 struct cache_pool : dynpool {
00324
00325
00326 NORET cache_pool(size_t cs, size_t cc, size_t l2bs, size_t mb)
00327 : dynpool(cs, cc, l2bs, mb)
00328 {
00329 }
00330
00331 virtual void _release_block(mblock* b);
00332 virtual mblock* _acquire_block();
00333 virtual NORET ~cache_pool();
00334 };
00335
00336 typedef block_pool<T, cache_pool, MaxBytes> Pool;
00337
00338 Pool _pool;
00339
00340 };
00341
00342 template <class T, class TF, size_t M>
00343 inline
00344 void object_cache<T,TF,M>::cache_pool::_release_block(mblock* b) {
00345 union { cache_pool* cp; memory_block::block_list* bl; } u={this};
00346 b->_owner = u.bl;
00347 dynpool::_release_block(b);
00348 }
00349
00350
00351
00352
00353 template <class T, class TF, size_t M>
00354 inline
00355 dynpool::mblock* object_cache<T,TF,M>::cache_pool::_acquire_block() {
00356 dynpool::mblock* b = dynpool::_acquire_block();
00357 void* me = this;
00358 if(me != b->_owner) {
00359
00360 for(size_t j=0; j < Pool::chip_count(); j++)
00361 TF::construct(b->_get(j, Pool::chip_size()));
00362 b->_owner = 0;
00363 }
00364 return b;
00365 }
00366
00367
00368
00369 template <class T, class TF, size_t M>
00370 inline
00371 NORET object_cache<T,TF,M>::cache_pool::~cache_pool() {
00372 size_t size = _size();
00373 for(size_t i=0; i < size; i++) {
00374 mblock* b = _at(i);
00375 for(size_t j=0; j < Pool::chip_count(); j++) {
00376 union { char* c; T* t; } u = {b->_get(j, Pool::chip_size())};
00377 u.t->~T();
00378 }
00379 }
00380 }
00381
00382
00383 #endif