1 #ifndef __BLOCK_ALLOC_H 2 #define __BLOCK_ALLOC_H 17 template<
class T,
size_t MaxBytes>
class block_alloc;
19 template<
class T,
size_t MaxBytes>
inline void*
operator new(
size_t nbytes, block_alloc<T, MaxBytes>& alloc);
21 template<
class T,
size_t MaxBytes>
inline void operator delete(
void* ptr, block_alloc<T, MaxBytes>& alloc);
24 struct dynpool :
public memory_block::block_pool {
25 typedef memory_block::block mblock;
27 pthread_mutex_t _lock;
32 std::deque<mblock*> _free_list;
38 size_t _log2_block_size;
42 dynpool(
size_t chip_size,
size_t chip_count,
43 size_t log2_block_size,
size_t max_bytes);
47 virtual bool validate_pointer(
void* ptr);
53 mblock* _at(
size_t i);
56 mblock* _acquire_block();
58 virtual void _release_block(mblock* b);
101 template<
class T,
class Pool=dynpool,
size_t MaxBytes = 0>
103 typedef memory_block::meta_block_size<sizeof(T)> BlockSize;
106 static size_t block_size() {
107 return BlockSize::BYTES;
110 static size_t chip_count() {
111 return BlockSize::COUNT;
114 static size_t chip_size() {
119 #define TEMPLATE_ARGS chip_size(), chip_count(), block_size() 121 static Pool* get_static_pool() {
122 static Pool p(chip_size(), chip_count(), BlockSize::LOG2,
123 MaxBytes ? MaxBytes : 1024 * 1024 * 1024);
128 _blist(get_static_pool(), TEMPLATE_ARGS) {}
133 return _blist.acquire(TEMPLATE_ARGS);
140 static void release(
void* ptr) {
141 w_assert0(get_static_pool()->validate_pointer(ptr));
142 memory_block::block::release_chip(ptr, TEMPLATE_ARGS);
146 memory_block::block_list _blist;
149 template<
class T,
size_t MaxBytes = 0>
151 typedef block_pool<T, dynpool, MaxBytes>
Pool;
153 static void destroy_object(
T* ptr) {
154 if (ptr ==
nullptr) {
168 friend void*
operator new<>(size_t, block_alloc<T, MaxBytes>&);
170 friend void operator delete<>(
void*, block_alloc<T, MaxBytes>&);
173 template<
class T,
size_t MaxBytes>
175 void*
operator new(
size_t nbytes, block_alloc<T, MaxBytes>& alloc) {
178 return alloc._pool.acquire();
185 template<
class T,
size_t MaxBytes>
187 void operator delete(
void* ptr, block_alloc<T, MaxBytes>& ) {
188 if (ptr ==
nullptr) {
191 block_alloc<T, MaxBytes>::Pool::release(ptr);
196 size_t dynpool::_size()
const {
197 return _arr_end >> _log2_block_size;
201 dynpool::mblock* dynpool::_at(
size_t i) {
202 size_t offset = i << _log2_block_size;
206 } u = {_arr + offset};
214 struct object_cache_default_factory {
217 construct(
void* ptr) {
225 init(
T* t) {
return t;
230 struct object_cache_initializing_factory {
233 construct(
void* ptr) {
250 static T* init(
T* t, Arg1 arg1) {
255 template<
class Arg1,
class Arg2>
256 static T* init(
T* t, Arg1 arg1, Arg2 arg2) {
261 template<
class Arg1,
class Arg2,
class Arg3>
262 static T* init(
T* t, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
263 t->init(arg1, arg2, arg3);
268 template<
class T,
class TFactory=
object_cache_default_factory<T>,
size_t MaxBytes = 0>
269 struct object_cache {
273 return TFactory::init(_acquire());
277 T* acquire(Arg1 arg1) {
278 return TFactory::init(_acquire(), arg1);
281 template<
class Arg1,
class Arg2>
282 T* acquire(Arg1 arg1, Arg2 arg2) {
283 return TFactory::init(_acquire(), arg1, arg2);
286 template<
class Arg1,
class Arg2,
class Arg3>
287 T* acquire(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
288 return TFactory::init(_acquire(), arg1, arg2, arg3);
296 } u = {_pool.acquire()};
300 static void release(
T* obj) {
301 TFactory::reset(obj);
307 struct cache_pool :
public dynpool {
310 cache_pool(
size_t cs,
size_t cc,
size_t l2bs,
size_t mb) :
311 dynpool(cs, cc, l2bs, mb) {}
313 virtual void _release_block(mblock* b);
315 virtual mblock* _acquire_block();
317 virtual ~cache_pool();
320 typedef block_pool<T, cache_pool, MaxBytes> Pool;
325 template<
class T,
class TF,
size_t M>
327 void object_cache<T, TF, M>::cache_pool::_release_block(mblock* b) {
330 memory_block::block_list* bl;
333 dynpool::_release_block(b);
339 template<
class T,
class TF,
size_t M>
341 dynpool::mblock* object_cache<T, TF, M>::cache_pool::_acquire_block() {
342 dynpool::mblock* b = dynpool::_acquire_block();
344 if (me != b->_owner) {
346 for (
size_t j = 0; j < Pool::chip_count(); j++) {
347 TF::construct(b->_get(j, Pool::chip_size()));
356 template<
class T,
class TF,
size_t M>
358 object_cache<T, TF, M>::cache_pool::~cache_pool() {
359 size_t size = _size();
360 for (
size_t i = 0; i < size; i++) {
362 for (
size_t j = 0; j < Pool::chip_count(); j++) {
366 } u = {b->_get(j, Pool::chip_size())};
377 typedef dynpool Pool;
379 typedef memory_block::block_list BlockList;
385 size_t nbytes()
const {
392 void destroy(
void* ptr);
410 void*
operator new(
size_t nbytes,
blob_pool& alloc) {
412 return alloc.acquire();
420 void operator delete(
void* ptr,
blob_pool& alloc) {
427 #endif // __BLOCK_ALLOC_H Simple pool class.
Definition: stl_pool.h:40
#define w_assert1(x)
Level 1 should not add significant extra time.
Definition: w_base.h:198
#define w_assert2(x)
Level 2 adds some time.
Definition: w_base.h:206
#define w_assert0(x)
Default assert/debug level is 0.
Definition: w_base.h:175
#define T
Definition: w_okvl_inl.h:45