22 #ifndef BBOOST_POOL_HPP
23 #define BBOOST_POOL_HPP
25 #include <type_traits>
30 #pragma push_macro("max")
31 #pragma push_macro("min")
35 #define BBOOST_NO_INCLASS_MEMBER_INITIALIZATION
36 #define BBOOST_ASSERT(X) BeAssert((X))
38 # ifdef BBOOST_NO_INCLASS_MEMBER_INITIALIZATION
39 # define BBOOST_STATIC_CONSTANT(type, assignment) enum { assignment }
41 # define BBOOST_STATIC_CONSTANT(type, assignment) static const type assignment
62 #define BBOOST_PTR_SIZE sizeof(void *)
64 #define BBOOSTE_MIN_ALIGNMENT std::alignment_of<void *>::value
73 #ifdef BBOOST_POOL_INSTRUMENT
87 #pragma warning(disable:4127) // Conditional expression is constant
96 template <
typename SizeType>
125 typedef SizeType size_type;
126 static_assert (
sizeof(
void*) ==
sizeof(size_type),
"simplifying assumption");
132 char * ptr_next_size()
const
134 return (ptr + sz -
sizeof(size_type));
136 char * ptr_next_ptr()
const
138 return (ptr_next_size() - BBOOST_PTR_SIZE);
142 PODptr(
char *
const nptr,
const size_type nsize)
143 :ptr(nptr), sz(nsize)
156 return (
begin() != 0);
176 return ptr_next_ptr();
178 size_type total_size()
const
185 size_type element_size()
const
187 return static_cast<size_type
>(sz -
sizeof(size_type) - BBOOST_PTR_SIZE);
190 size_type & next_size()
const
192 return *(
static_cast<size_type *
>(
static_cast<void*
>((ptr_next_size()))));
195 char * & next_ptr()
const
197 return *(
static_cast<char **
>(
static_cast<void*
>(ptr_next_ptr())));
202 return PODptr<size_type>(next_ptr(), next_size());
204 void next(
const PODptr & arg)
const
206 next_ptr() = arg.begin();
207 next_size() = arg.total_size();
249 template <
typename UserAllocator>
250 class bpool:
protected simple_segregated_storage < typename UserAllocator::size_type >
253 typedef UserAllocator user_allocator;
254 typedef typename UserAllocator::size_type size_type;
255 typedef typename UserAllocator::difference_type difference_type;
256 static_assert (
sizeof(
void*) ==
sizeof(size_type),
"simplifying assumption");
259 BBOOST_STATIC_CONSTANT(size_type, min_alloc_size = BBOOST_PTR_SIZE );
260 BBOOST_STATIC_CONSTANT(size_type, min_align = BBOOSTE_MIN_ALIGNMENT );
264 void * malloc_need_resize();
265 void * ordered_malloc_need_resize();
268 details::PODptr<size_type> list;
270 simple_segregated_storage<size_type> & store()
274 const simple_segregated_storage<size_type> & store()
const
278 const size_type requested_size;
280 size_type start_size;
284 details::PODptr<size_type> find_POD(
void *
const chunk)
const;
287 static bool is_from(
void *
const chunk,
char *
const i,
288 const size_type sizeof_i)
308 std::less_equal<void *> lt_eq;
309 std::less<void *> lt;
310 return (lt_eq(i, chunk) && lt(chunk, i + sizeof_i));
313 size_type alloc_size()
const
319 size_type s = std::max<size_type> (requested_size, min_alloc_size);
320 size_type rem = s % min_align;
322 s += min_align - rem;
323 BBOOST_ASSERT(s >= min_alloc_size);
324 BBOOST_ASSERT(s % min_align == 0);
328 static void * & nextof(
void *
const ptr)
330 return *(
static_cast<void **
>(ptr));
336 explicit bpool(
const size_type nrequested_size,
337 const size_type nnext_size = 32,
338 const size_type nmax_size = 0)
340 list(0, 0), requested_size(nrequested_size), next_size(nnext_size), start_size(nnext_size),
max_size(nmax_size)
358 bool release_memory();
364 size_type get_next_size()
const
369 void set_next_size(
const size_type nnext_size)
371 next_size = start_size = nnext_size;
374 size_type get_max_size()
const
378 void set_max_size(
const size_type nmax_size)
382 size_type get_requested_size()
const
384 return requested_size;
399 if (!store().
empty())
400 return (store().malloc)();
401 return malloc_need_resize();
404 void * ordered_malloc()
409 if (!store().
empty())
410 return (store().malloc)();
411 return ordered_malloc_need_resize();
416 void * ordered_malloc(size_type n);
423 void free (
void *
const chunk)
425 (store().free)(chunk);
436 void ordered_free(
void *
const chunk)
438 store().ordered_free(chunk);
446 void free (
void *
const chunks,
const size_type n)
448 const size_type partition_size = alloc_size();
454 const size_type total_req_size = n * requested_size;
455 const size_type num_chunks = total_req_size / partition_size +
456 ((total_req_size % partition_size) ?
true :
false);
458 store().free_n(chunks, num_chunks, partition_size);
463 void ordered_free(
void *
const chunks,
const size_type n)
470 const size_type partition_size = alloc_size();
471 const size_type total_req_size = n * requested_size;
472 const size_type num_chunks = total_req_size / partition_size +
473 ((total_req_size % partition_size) ?
true :
false);
475 store().ordered_free_n(chunks, num_chunks, partition_size);
479 bool is_from(
void *
const chunk)
const
481 return (find_POD(chunk).valid());
490 #ifndef BBOOST_NO_INCLASS_MEMBER_INITIALIZATION
491 template <
typename UserAllocator>
492 typename bpool<UserAllocator>::size_type
const bpool<UserAllocator>::min_alloc_size;
493 template <
typename UserAllocator>
494 typename bpool<UserAllocator>::size_type
const bpool<UserAllocator>::min_align;
497 template <
typename UserAllocator>
498 bool bpool<UserAllocator>::release_memory()
507 details::PODptr<size_type> ptr = list;
508 details::PODptr<size_type> prev;
514 void * free_p = this->first;
515 void * prev_free_p = 0;
517 const size_type partition_size = alloc_size();
542 bool all_chunks_free =
true;
546 void * saved_free = free_p;
547 for (
char * i = ptr.begin(); i != ptr.end(); i += partition_size)
553 all_chunks_free =
false;
563 free_p = nextof(free_p);
569 const details::PODptr<size_type> next = ptr.next();
571 if (!all_chunks_free)
573 if (is_from(free_p, ptr.begin(), ptr.element_size()))
575 std::less<void *> lt;
576 void *
const end = ptr.end();
579 prev_free_p = free_p;
580 free_p = nextof(free_p);
581 }
while (free_p && lt(free_p, end));
604 if (prev_free_p != 0)
605 nextof(prev_free_p) = free_p;
607 this->first = free_p;
610 (UserAllocator::free)(ptr.begin());
618 next_size = start_size;
622 template <
typename UserAllocator>
623 bool bpool<UserAllocator>::purge_memory()
631 details::PODptr<size_type> iter = list;
639 const details::PODptr<size_type> next = iter.next();
642 (UserAllocator::free)(iter.begin());
646 }
while (iter.valid());
650 next_size = start_size;
655 template <
typename UserAllocator>
656 void * bpool<UserAllocator>::malloc_need_resize()
658 size_type partition_size = alloc_size();
661 size_type POD_size =
static_cast<size_type
>(next_size * partition_size + BBOOST_PTR_SIZE +
sizeof(size_type));
662 char * ptr = (UserAllocator::malloc)(POD_size);
668 partition_size = alloc_size();
669 POD_size =
static_cast<size_type
>(next_size * partition_size + BBOOST_PTR_SIZE +
sizeof(size_type));
670 ptr = (UserAllocator::malloc)(POD_size);
675 const details::PODptr<size_type> node(ptr, POD_size);
679 else if( next_size*partition_size/requested_size <
max_size)
680 next_size =
std::min (next_size << 1,
max_size*requested_size/ partition_size);
683 store().add_block(node.begin(), node.element_size(), partition_size);
690 return (store().malloc)();
693 template <
typename UserAllocator>
694 void * bpool<UserAllocator>::ordered_malloc_need_resize()
696 size_type partition_size = alloc_size();
698 size_type POD_size =
static_cast<size_type
>(next_size * partition_size + BBOOST_PTR_SIZE +
sizeof(size_type));
699 char * ptr = (UserAllocator::malloc)(POD_size);
705 partition_size = alloc_size();
706 POD_size =
static_cast<size_type
>(next_size * partition_size + BBOOST_PTR_SIZE +
sizeof(size_type));
707 ptr = (UserAllocator::malloc)(POD_size);
712 const details::PODptr<size_type> node(ptr, POD_size);
716 else if( next_size*partition_size/requested_size <
max_size)
717 next_size =
std::min (next_size << 1,
max_size*requested_size/ partition_size);
723 store().add_ordered_block(node.begin(), node.element_size(), partition_size);
727 if (!list.valid() || std::greater<void *>()(list.begin(), node.begin()))
734 details::PODptr<size_type> prev = list;
740 if (prev.next_ptr() == 0
741 || std::greater<void *>()(prev.next_ptr(), node.begin()))
747 node.next(prev.next());
751 return (store().malloc)();
754 template <
typename UserAllocator>
755 void * bpool<UserAllocator>::ordered_malloc(
const size_type n)
760 const size_type partition_size = alloc_size();
761 const size_type total_req_size = n * requested_size;
762 const size_type num_chunks = total_req_size / partition_size +
763 ((total_req_size % partition_size) ?
true :
false);
765 void * ret = store().malloc_n(num_chunks, partition_size);
767 #ifdef BBOOST_POOL_INSTRUMENT
768 std::cout <<
"Allocating " << n <<
" chunks from bpool of size " << partition_size << std::endl;
770 if ((ret != 0) || (n == 0))
773 #ifdef BBOOST_POOL_INSTRUMENT
774 std::cout <<
"Cache miss, allocating another chunk...\n";
778 next_size =
std::max (next_size, num_chunks);
779 size_type POD_size =
static_cast<size_type
>(next_size * partition_size + BBOOST_PTR_SIZE +
sizeof(size_type));
780 char * ptr = (UserAllocator::malloc)(POD_size);
784 if(num_chunks < next_size)
789 next_size =
std::max (next_size, num_chunks);
790 POD_size =
static_cast<size_type
>(next_size * partition_size + BBOOST_PTR_SIZE +
sizeof(size_type));
791 ptr = (UserAllocator::malloc)(POD_size);
796 const details::PODptr<size_type> node(ptr, POD_size);
799 if (next_size > num_chunks)
800 store().add_ordered_block(node.begin() + num_chunks * partition_size,
801 node.element_size() - num_chunks * partition_size, partition_size);
805 else if( next_size*partition_size/requested_size <
max_size)
806 next_size =
std::min (next_size << 1,
max_size*requested_size/ partition_size);
810 if (!list.valid() || std::greater<void *>()(list.begin(), node.begin()))
817 details::PODptr<size_type> prev = list;
822 if (prev.next_ptr() == 0
823 || std::greater<void *>()(prev.next_ptr(), node.begin()))
829 node.next(prev.next());
837 template <
typename UserAllocator>
838 details::PODptr<typename bpool<UserAllocator>::size_type>
839 bpool<UserAllocator>::find_POD(
void *
const chunk)
const
843 details::PODptr<size_type> iter = list;
846 if (is_from(chunk, iter.begin(), iter.element_size()))
859 #pragma pop_macro("max")
860 #pragma pop_macro("min")
863 #endif // #ifdef BBOOST_POOL_HPP
bool empty() const
Definition: stdcxx/bstdmap.h:210
#define min(x, y)
Definition: MathUtils.h:21
iterator begin()
Definition: stdcxx/bstdmap.h:178
iterator end()
Definition: stdcxx/bstdmap.h:186
Provides Bentley specific assert functions (Bentley/BeAssert.h).
#define max(x, y)
Definition: MathUtils.h:24
size_type max_size() const
Definition: stdcxx/bstdmap.h:218