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 : public 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_static_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_static_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 w_assert0(get_static_pool()->validate_pointer(ptr));
00190 memory_block::block::release_chip(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 if(ptr == NULL) return;
00206
00207 ptr->~T();
00208 Pool::release(ptr);
00209
00210
00211 }
00212
00213 private:
00214 Pool _pool;
00215
00216
00217 friend void* operator new<>(size_t, block_alloc<T,MaxBytes> &);
00218 friend void operator delete<>(void*, block_alloc<T,MaxBytes> &);
00219 };
00220
00221 template<class T, size_t MaxBytes>
00222 inline
00223 void* operator new(size_t nbytes, block_alloc<T,MaxBytes> &alloc)
00224 {
00225 (void) nbytes;
00226 w_assert1(nbytes == sizeof(T));
00227 return alloc._pool.acquire();
00228 }
00229
00230
00231
00232
00233
00234 template<class T, size_t MaxBytes>
00235 inline
00236 void operator delete(void* ptr, block_alloc<T,MaxBytes> & )
00237 {
00238 if(ptr == NULL) return;
00239 block_alloc<T,MaxBytes>::Pool::release(ptr);
00240 w_assert2(0);
00241 }
00242
00243 inline
00244 size_t dynpool::_size() const {
00245 return _arr_end >> _log2_block_size;
00246 }
00247
00248 inline
00249 dynpool::mblock* dynpool::_at(size_t i) {
00250 size_t offset = i << _log2_block_size;
00251 union { char* c; mblock* b; } u = {_arr+offset};
00252 return u.b;
00253 }
00254
00255
00256
00257 #undef TEMPLATE_ARGS
00258
00259
00260 template<class T>
00261 struct object_cache_default_factory {
00262
00263 static T*
00264 construct(void* ptr) { return new (ptr) T; }
00265
00266 static void
00267 reset(T* t) { }
00268
00269 static T*
00270 init(T* t) { return t; }
00271 };
00272
00273 template<class T>
00274 struct object_cache_initializing_factory {
00275
00276 static T*
00277 construct(void* ptr) { return new (ptr) T; }
00278
00279 static void
00280 reset(T* t) { t->reset(); }
00281
00282 static T*
00283 init(T* t) { t->init(); return t; }
00284
00285
00286 template<class Arg1>
00287 static T* init(T* t, Arg1 arg1) { t->init(arg1); return t; }
00288 template<class Arg1, class Arg2>
00289 static T* init(T* t, Arg1 arg1, Arg2 arg2) { t->init(arg1, arg2); return t; }
00290 template<class Arg1, class Arg2, class Arg3>
00291 static T* init(T* t, Arg1 arg1, Arg2 arg2, Arg3 arg3) { t->init(arg1, arg2, arg3); return t; }
00292 };
00293
00294 template <class T, class TFactory=object_cache_default_factory<T>, size_t MaxBytes=0>
00295 struct object_cache {
00296
00297
00298 T* acquire() {
00299 return TFactory::init(_acquire());
00300 }
00301 template<class Arg1>
00302 T* acquire(Arg1 arg1) {
00303 return TFactory::init(_acquire(), arg1);
00304 }
00305 template<class Arg1, class Arg2>
00306 T* acquire(Arg1 arg1, Arg2 arg2) {
00307 return TFactory::init(_acquire(), arg1, arg2);
00308 }
00309 template<class Arg1, class Arg2, class Arg3>
00310 T* acquire(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
00311 return TFactory::init(_acquire(), arg1, arg2, arg3);
00312 }
00313
00314 T* _acquire() {
00315
00316 union { void* v; T* t; } u = {_pool.acquire()};
00317 return u.t;
00318 }
00319
00320 static
00321 void release(T* obj) {
00322 TFactory::reset(obj);
00323 Pool::release(obj);
00324 }
00325
00326 private:
00327
00328 struct cache_pool : public dynpool {
00329
00330
00331 NORET cache_pool(size_t cs, size_t cc, size_t l2bs, size_t mb)
00332 : dynpool(cs, cc, l2bs, mb)
00333 {
00334 }
00335
00336 virtual void _release_block(mblock* b);
00337 virtual mblock* _acquire_block();
00338 virtual NORET ~cache_pool();
00339 };
00340
00341 typedef block_pool<T, cache_pool, MaxBytes> Pool;
00342
00343 Pool _pool;
00344
00345 };
00346
00347 template <class T, class TF, size_t M>
00348 inline
00349 void object_cache<T,TF,M>::cache_pool::_release_block(mblock* b) {
00350 union { cache_pool* cp; memory_block::block_list* bl; } u={this};
00351 b->_owner = u.bl;
00352 dynpool::_release_block(b);
00353 }
00354
00355
00356
00357
00358 template <class T, class TF, size_t M>
00359 inline
00360 dynpool::mblock* object_cache<T,TF,M>::cache_pool::_acquire_block() {
00361 dynpool::mblock* b = dynpool::_acquire_block();
00362 void* me = this;
00363 if(me != b->_owner) {
00364
00365 for(size_t j=0; j < Pool::chip_count(); j++)
00366 TF::construct(b->_get(j, Pool::chip_size()));
00367 b->_owner = 0;
00368 }
00369 return b;
00370 }
00371
00372
00373
00374 template <class T, class TF, size_t M>
00375 inline
00376 NORET object_cache<T,TF,M>::cache_pool::~cache_pool() {
00377 size_t size = _size();
00378 for(size_t i=0; i < size; i++) {
00379 mblock* b = _at(i);
00380 for(size_t j=0; j < Pool::chip_count(); j++) {
00381 union { char* c; T* t; } u = {b->_get(j, Pool::chip_size())};
00382 u.t->~T();
00383 }
00384 }
00385 }
00386
00387
00388 #endif