30 #ifndef _MT_ALLOCATOR_H
31 #define _MT_ALLOCATOR_H 1
39 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
44 typedef
void (*__destroy_handler)(
void*);
51 typedef unsigned short int _Binmap_type;
58 enum { _S_align = 8 };
59 enum { _S_max_bytes = 128 };
60 enum { _S_min_bin = 8 };
61 enum { _S_chunk_size = 4096 - 4 *
sizeof(
void*) };
62 enum { _S_max_threads = 4096 };
63 enum { _S_freelist_headroom = 10 };
96 size_t _M_max_threads;
104 size_t _M_freelist_headroom;
111 : _M_align(_S_align), _M_max_bytes(_S_max_bytes), _M_min_bin(_S_min_bin),
112 _M_chunk_size(_S_chunk_size), _M_max_threads(_S_max_threads),
113 _M_freelist_headroom(_S_freelist_headroom),
114 _M_force_new(std::getenv(
"GLIBCXX_FORCE_NEW") ?
true :
false)
118 _Tune(
size_t __align,
size_t __maxb,
size_t __minbin,
size_t __chunk,
119 size_t __maxthreads,
size_t __headroom,
bool __force)
120 : _M_align(__align), _M_max_bytes(__maxb), _M_min_bin(__minbin),
121 _M_chunk_size(__chunk), _M_max_threads(__maxthreads),
122 _M_freelist_headroom(__headroom), _M_force_new(__force)
126 struct _Block_address
129 _Block_address* _M_next;
133 _M_get_options()
const
134 {
return _M_options; }
137 _M_set_options(_Tune __t)
144 _M_check_threshold(
size_t __bytes)
145 {
return __bytes > _M_options._M_max_bytes || _M_options._M_force_new; }
148 _M_get_binmap(
size_t __bytes)
149 {
return _M_binmap[__bytes]; }
153 {
return _M_options._M_align; }
157 : _M_options(_Tune()), _M_binmap(NULL), _M_init(
false) { }
160 __pool_base(
const _Tune& __options)
161 : _M_options(__options), _M_binmap(NULL), _M_init(
false) { }
165 __pool_base(
const __pool_base&);
168 operator=(
const __pool_base&);
174 _Binmap_type* _M_binmap;
187 template<
bool _Thread>
198 _Block_record* _M_next;
204 _Block_record** _M_first;
207 _Block_address* _M_address;
213 if (__builtin_expect(_M_init ==
false,
false))
218 _M_destroy()
throw();
221 _M_reserve_block(
size_t __bytes,
const size_t __thread_id);
224 _M_reclaim_block(
char* __p,
size_t __bytes);
227 _M_get_thread_id() {
return 0; }
230 _M_get_bin(
size_t __which)
231 {
return _M_bin[__which]; }
234 _M_adjust_freelist(
const _Bin_record&, _Block_record*,
size_t)
238 : _M_bin(NULL), _M_bin_size(1) { }
240 explicit __pool(
const __pool_base::_Tune& __tune)
241 : __pool_base(__tune), _M_bin(NULL), _M_bin_size(1) { }
271 struct _Thread_record
274 _Thread_record* _M_next;
283 _Block_record* _M_next;
294 _Block_record** _M_first;
297 _Block_address* _M_address;
314 __gthread_mutex_t* _M_mutex;
319 _M_initialize(__destroy_handler);
324 if (__builtin_expect(_M_init ==
false,
false))
329 _M_destroy()
throw();
332 _M_reserve_block(
size_t __bytes,
const size_t __thread_id);
335 _M_reclaim_block(
char* __p,
size_t __bytes);
338 _M_get_bin(
size_t __which)
339 {
return _M_bin[__which]; }
342 _M_adjust_freelist(
const _Bin_record& __bin, _Block_record* __block,
345 if (__gthread_active_p())
347 __block->_M_thread_id = __thread_id;
348 --__bin._M_free[__thread_id];
349 ++__bin._M_used[__thread_id];
355 _M_destroy_thread_key(
void*);
361 : _M_bin(NULL), _M_bin_size(1), _M_thread_freelist(NULL)
364 explicit __pool(
const __pool_base::_Tune& __tune)
365 : __pool_base(__tune), _M_bin(NULL), _M_bin_size(1),
366 _M_thread_freelist(NULL)
378 _Thread_record* _M_thread_freelist;
379 void* _M_thread_freelist_initial;
386 template<
template <
bool>
class _PoolTp,
bool _Thread>
389 typedef _PoolTp<_Thread> pool_type;
394 static pool_type _S_pool;
399 template<
template <
bool>
class _PoolTp,
bool _Thread>
400 struct __common_pool_base;
402 template<
template <
bool>
class _PoolTp>
403 struct __common_pool_base<_PoolTp, false>
404 :
public __common_pool<_PoolTp, false>
406 using __common_pool<_PoolTp, false>::_S_get_pool;
412 if (__builtin_expect(__init ==
false,
false))
414 _S_get_pool()._M_initialize_once();
421 template<
template <
bool>
class _PoolTp>
422 struct __common_pool_base<_PoolTp, true>
423 :
public __common_pool<_PoolTp, true>
425 using __common_pool<_PoolTp, true>::_S_get_pool;
429 { _S_get_pool()._M_initialize_once(); }
435 if (__builtin_expect(__init ==
false,
false))
437 if (__gthread_active_p())
440 static __gthread_once_t __once = __GTHREAD_ONCE_INIT;
441 __gthread_once(&__once, _S_initialize);
447 _S_get_pool()._M_initialize_once();
455 template<
template <
bool>
class _PoolTp,
bool _Thread>
458 template<
typename _Tp1,
template <
bool>
class _PoolTp1 = _PoolTp,
459 bool _Thread1 = _Thread>
463 using __common_pool_base<_PoolTp, _Thread>::_S_get_pool;
464 using __common_pool_base<_PoolTp, _Thread>::_S_initialize_once;
468 template<
typename _Tp,
template <
bool>
class _PoolTp,
bool _Thread>
469 struct __per_type_pool
471 typedef _Tp value_type;
472 typedef _PoolTp<_Thread> pool_type;
478 typedef typename pool_type::_Block_record _Block_record;
479 const static size_t __a = (__alignof__(_Tp) >=
sizeof(_Block_record)
480 ? __alignof__(_Tp) :
sizeof(_Block_record));
482 typedef typename __pool_base::_Tune _Tune;
483 static _Tune _S_tune(__a,
sizeof(_Tp) * 64,
484 sizeof(_Tp) * 2 >= __a ?
sizeof(_Tp) * 2 : __a,
485 sizeof(_Tp) *
size_t(_Tune::_S_chunk_size),
486 _Tune::_S_max_threads,
487 _Tune::_S_freelist_headroom,
488 std::getenv(
"GLIBCXX_FORCE_NEW") ?
true :
false);
489 static pool_type _S_pool(_S_tune);
494 template<
typename _Tp,
template <
bool>
class _PoolTp,
bool _Thread>
495 struct __per_type_pool_base;
497 template<
typename _Tp,
template <
bool>
class _PoolTp>
498 struct __per_type_pool_base<_Tp, _PoolTp, false>
499 :
public __per_type_pool<_Tp, _PoolTp, false>
501 using __per_type_pool<_Tp, _PoolTp, false>::_S_get_pool;
507 if (__builtin_expect(__init ==
false,
false))
509 _S_get_pool()._M_initialize_once();
516 template<
typename _Tp,
template <
bool>
class _PoolTp>
517 struct __per_type_pool_base<_Tp, _PoolTp, true>
518 :
public __per_type_pool<_Tp, _PoolTp, true>
520 using __per_type_pool<_Tp, _PoolTp, true>::_S_get_pool;
524 { _S_get_pool()._M_initialize_once(); }
530 if (__builtin_expect(__init ==
false,
false))
532 if (__gthread_active_p())
535 static __gthread_once_t __once = __GTHREAD_ONCE_INIT;
536 __gthread_once(&__once, _S_initialize);
542 _S_get_pool()._M_initialize_once();
550 template<
typename _Tp,
template <
bool>
class _PoolTp,
bool _Thread>
552 :
public __per_type_pool_base<_Tp, _PoolTp, _Thread>
554 template<
typename _Tp1,
template <
bool>
class _PoolTp1 = _PoolTp,
555 bool _Thread1 = _Thread>
559 using __per_type_pool_base<_Tp, _PoolTp, _Thread>::_S_get_pool;
560 using __per_type_pool_base<_Tp, _PoolTp, _Thread>::_S_initialize_once;
565 template<
typename _Tp>
569 typedef size_t size_type;
570 typedef ptrdiff_t difference_type;
571 typedef _Tp* pointer;
572 typedef const _Tp* const_pointer;
573 typedef _Tp& reference;
574 typedef const _Tp& const_reference;
575 typedef _Tp value_type;
578 address(reference __x)
const
582 address(const_reference __x)
const
586 max_size()
const throw()
587 {
return size_t(-1) /
sizeof(_Tp); }
592 construct(pointer __p,
const _Tp& __val)
593 { ::new((
void *)__p) _Tp(__val); }
595 #ifdef __GXX_EXPERIMENTAL_CXX0X__
596 template<
typename... _Args>
598 construct(pointer __p, _Args&&... __args)
599 { ::new((
void *)__p) _Tp(std::forward<_Args>(__args)...); }
603 destroy(pointer __p) { __p->~_Tp(); }
607 #define __thread_default true
609 #define __thread_default false
623 template<
typename _Tp,
628 typedef size_t size_type;
629 typedef ptrdiff_t difference_type;
630 typedef _Tp* pointer;
631 typedef const _Tp* const_pointer;
632 typedef _Tp& reference;
633 typedef const _Tp& const_reference;
634 typedef _Tp value_type;
635 typedef _Poolp __policy_type;
636 typedef typename _Poolp::pool_type __pool_type;
638 template<
typename _Tp1,
typename _Poolp1 = _Poolp>
641 typedef typename _Poolp1::template _M_rebind<_Tp1>::other pol_type;
649 template<
typename _Tp1,
typename _Poolp1>
655 allocate(size_type __n,
const void* = 0);
658 deallocate(pointer __p, size_type __n);
660 const __pool_base::_Tune
664 return __policy_type::_S_get_pool()._M_get_options();
668 _M_set_options(__pool_base::_Tune __t)
669 { __policy_type::_S_get_pool()._M_set_options(__t); }
672 template<
typename _Tp,
typename _Poolp>
673 typename __mt_alloc<_Tp, _Poolp>::pointer
675 allocate(size_type __n,
const void*)
677 if (__builtin_expect(__n > this->max_size(),
false))
678 std::__throw_bad_alloc();
680 __policy_type::_S_initialize_once();
684 __pool_type&
__pool = __policy_type::_S_get_pool();
685 const size_t __bytes = __n *
sizeof(_Tp);
686 if (__pool._M_check_threshold(__bytes))
688 void* __ret = ::operator
new(__bytes);
689 return static_cast<_Tp*
>(__ret);
693 const size_t __which = __pool._M_get_binmap(__bytes);
694 const size_t __thread_id = __pool._M_get_thread_id();
699 typedef typename __pool_type::_Bin_record _Bin_record;
700 const _Bin_record& __bin = __pool._M_get_bin(__which);
701 if (__bin._M_first[__thread_id])
704 typedef typename __pool_type::_Block_record _Block_record;
705 _Block_record* __block = __bin._M_first[__thread_id];
706 __bin._M_first[__thread_id] = __block->_M_next;
708 __pool._M_adjust_freelist(__bin, __block, __thread_id);
709 __c =
reinterpret_cast<char*
>(__block) + __pool._M_get_align();
714 __c = __pool._M_reserve_block(__bytes, __thread_id);
716 return static_cast<_Tp*
>(
static_cast<void*
>(__c));
719 template<
typename _Tp,
typename _Poolp>
721 __mt_alloc<_Tp, _Poolp>::
722 deallocate(pointer __p, size_type __n)
724 if (__builtin_expect(__p != 0,
true))
728 __pool_type& __pool = __policy_type::_S_get_pool();
729 const size_t __bytes = __n *
sizeof(_Tp);
730 if (__pool._M_check_threshold(__bytes))
731 ::
operator delete(__p);
733 __pool._M_reclaim_block(reinterpret_cast<char*>(__p), __bytes);
737 template<
typename _Tp,
typename _Poolp>
739 operator==(
const __mt_alloc<_Tp, _Poolp>&,
const __mt_alloc<_Tp, _Poolp>&)
742 template<
typename _Tp,
typename _Poolp>
744 operator!=(
const __mt_alloc<_Tp, _Poolp>&,
const __mt_alloc<_Tp, _Poolp>&)
747 #undef __thread_default
749 _GLIBCXX_END_NAMESPACE
Base class for pool object.
Policy for shared __pool objects.
Base class for _Tp dependent member functions.
This is a fixed size (power of 2) allocator which - when compiled with thread support - will maintain...
Data describing the underlying memory pool, parameterized on threading support.
Policy for individual __pool objects.