29 #ifndef _BITMAP_ALLOCATOR_H
30 #define _BITMAP_ALLOCATOR_H 1
43 #define _BALLOC_ALIGN_BYTES 8
45 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
47 _GLIBCXX_BEGIN_NAMESPACE_VERSION
66 template<
typename _Tp>
73 typedef _Tp value_type;
75 typedef _Tp& reference;
76 typedef const _Tp& const_reference;
77 typedef std::size_t size_type;
78 typedef std::ptrdiff_t difference_type;
79 typedef pointer iterator;
84 pointer _M_end_of_storage;
87 _M_space_left()
const throw()
88 {
return _M_end_of_storage - _M_finish; }
90 _GLIBCXX_NODISCARD pointer
91 allocate(size_type __n)
92 {
return static_cast<pointer
>(::operator
new(__n *
sizeof(_Tp))); }
95 deallocate(pointer __p, size_type)
96 { ::operator
delete(__p); }
104 : _M_start(0), _M_finish(0), _M_end_of_storage(0) { }
108 {
return _M_finish - _M_start; }
111 begin()
const throw()
112 {
return this->_M_start; }
116 {
return this->_M_finish; }
120 {
return *(this->end() - 1); }
123 operator[](
const size_type __pos)
const throw()
124 {
return this->_M_start[__pos]; }
127 insert(iterator __pos, const_reference __x);
130 push_back(const_reference __x)
132 if (this->_M_space_left())
138 this->insert(this->end(), __x);
143 { --this->_M_finish; }
146 erase(iterator __pos)
throw();
150 { this->_M_finish = this->_M_start; }
154 template<
typename _Tp>
156 insert(iterator __pos, const_reference __x)
158 if (this->_M_space_left())
160 size_type __to_move = this->_M_finish - __pos;
161 iterator __dest = this->
end();
162 iterator __src = this->
end() - 1;
168 --__dest; --__src; --__to_move;
174 size_type __new_size = this->size() ? this->size() * 2 : 1;
175 iterator __new_start = this->allocate(__new_size);
176 iterator __first = this->
begin();
177 iterator __start = __new_start;
178 while (__first != __pos)
181 ++__start; ++__first;
185 while (__first != this->
end())
188 ++__start; ++__first;
191 this->deallocate(this->_M_start, this->size());
193 this->_M_start = __new_start;
194 this->_M_finish = __start;
195 this->_M_end_of_storage = this->_M_start + __new_size;
199 template<
typename _Tp>
200 void __mini_vector<_Tp>::
201 erase(iterator __pos)
throw()
203 while (__pos + 1 != this->
end())
212 template<
typename _Tp>
213 struct __mv_iter_traits
215 typedef typename _Tp::value_type value_type;
216 typedef typename _Tp::difference_type difference_type;
219 template<
typename _Tp>
220 struct __mv_iter_traits<_Tp*>
222 typedef _Tp value_type;
223 typedef std::ptrdiff_t difference_type;
229 bits_per_block =
sizeof(std::size_t) * std::size_t(bits_per_byte)
232 template<
typename _ForwardIterator,
typename _Tp,
typename _Compare>
234 __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
235 const _Tp& __val, _Compare __comp)
237 typedef typename __mv_iter_traits<_ForwardIterator>::difference_type
240 _DistanceType __len = __last - __first;
241 _DistanceType __half;
242 _ForwardIterator __middle;
249 if (__comp(*__middle, __val))
253 __len = __len - __half - 1;
264 template<
typename _AddrPair>
267 {
return (__ap.second - __ap.first) + 1; }
272 template<
typename _AddrPair>
275 {
return __num_blocks(__ap) / std::size_t(bits_per_block); }
278 template<
typename _Tp>
279 class _Inclusive_between
283 pointer _M_ptr_value;
287 _Inclusive_between(pointer __ptr) : _M_ptr_value(__ptr)
291 operator()(_Block_pair __bp)
const throw()
302 template<
typename _Functor>
305 typename _Functor::result_type>
310 typedef typename _Functor::argument_type argument_type;
311 typedef typename _Functor::result_type result_type;
313 _Functor_Ref(_Functor& __fref) : _M_fref(__fref)
317 operator()(argument_type __arg)
318 {
return _M_fref(__arg); }
328 template<
typename _Tp>
334 typedef typename _BPVector::difference_type _Counter_type;
336 std::size_t* _M_pbitmap;
337 _Counter_type _M_data_offset;
359 if (*(
reinterpret_cast<size_t*
>
363 size_t* __rover =
reinterpret_cast<size_t*
>(__bp.
first) - 1;
365 for (_Counter_type __i = 0; __i < __diff; ++__i)
367 _M_data_offset = __i;
370 _M_pbitmap = __rover;
379 _M_get()
const throw()
380 {
return _M_pbitmap; }
383 _M_offset()
const throw()
384 {
return _M_data_offset * std::size_t(bits_per_block); }
394 template<
typename _Tp>
399 typedef typename _BPVector::size_type _Index_type;
403 std::size_t* _M_curr_bmap;
404 std::size_t* _M_last_bmap_in_block;
405 _Index_type _M_curr_index;
412 { this->_M_reset(__index); }
415 _M_reset(
long __index = -1)
throw()
420 _M_curr_index =
static_cast<_Index_type
>(-1);
424 _M_curr_index = __index;
425 _M_curr_bmap =
reinterpret_cast<std::size_t*
>
426 (_M_vbp[_M_curr_index].first) - 1;
428 _GLIBCXX_DEBUG_ASSERT(__index <= (
long)_M_vbp.size() - 1);
430 _M_last_bmap_in_block = _M_curr_bmap
431 - ((_M_vbp[_M_curr_index].second
432 - _M_vbp[_M_curr_index].first + 1)
433 / std::size_t(bits_per_block) - 1);
440 _M_set_internal_bitmap(std::size_t* __new_internal_marker)
throw()
441 { _M_curr_bmap = __new_internal_marker; }
444 _M_finished()
const throw()
445 {
return(_M_curr_bmap == 0); }
450 if (_M_curr_bmap == _M_last_bmap_in_block)
452 if (++_M_curr_index == _M_vbp.size())
455 this->_M_reset(_M_curr_index);
463 _M_get()
const throw()
464 {
return _M_curr_bmap; }
467 _M_base()
const throw()
468 {
return _M_vbp[_M_curr_index].first; }
471 _M_offset()
const throw()
473 return std::size_t(bits_per_block)
474 * ((
reinterpret_cast<std::size_t*
>(this->_M_base())
475 - _M_curr_bmap) - 1);
479 _M_where()
const throw()
480 {
return _M_curr_index; }
489 std::size_t __mask = 1 << __pos;
500 std::size_t __mask = 1 << __pos;
509 {
return static_cast<std::size_t
>(__builtin_ctzl(__num)); }
519 typedef std::size_t* value_type;
521 typedef vector_type::iterator iterator;
522 typedef __mutex __mutex_type;
525 struct _LT_pointer_compare
528 operator()(
const std::size_t* __pui,
529 const std::size_t __cui)
const throw()
530 {
return *__pui < __cui; }
533 #if defined __GTHREADS
537 static __mutex_type _S_mutex;
560 _M_validate(std::size_t* __addr)
throw()
563 const vector_type::size_type __max_size = 64;
564 if (__free_list.size() >= __max_size)
568 if (*__addr >= *__free_list.back())
573 ::operator
delete(
static_cast<void*
>(__addr));
580 ::operator
delete(
static_cast<void*
>(__free_list.back()));
581 __free_list.pop_back();
586 iterator __temp = __detail::__lower_bound
587 (__free_list.begin(), __free_list.end(),
588 *__addr, _LT_pointer_compare());
591 __free_list.insert(__temp, __addr);
606 _M_should_i_give(std::size_t __block_size,
607 std::size_t __required_size)
throw()
609 const std::size_t __max_wastage_percentage = 36;
610 if (__block_size >= __required_size &&
611 (((__block_size - __required_size) * 100 / __block_size)
612 < __max_wastage_percentage))
628 #if defined __GTHREADS
633 this->_M_validate(
reinterpret_cast<std::size_t*
>(__addr) - 1);
657 template<
typename _Tp>
665 typedef void* pointer;
666 typedef const void* const_pointer;
669 typedef void value_type;
670 template<
typename _Tp1>
681 template<
typename _Tp>
685 typedef std::size_t size_type;
686 typedef std::ptrdiff_t difference_type;
687 typedef _Tp* pointer;
688 typedef const _Tp* const_pointer;
689 typedef _Tp& reference;
690 typedef const _Tp& const_reference;
691 typedef _Tp value_type;
692 typedef free_list::__mutex_type __mutex_type;
694 template<
typename _Tp1>
700 #if __cplusplus >= 201103L
707 template<std::
size_t _BSize, std::
size_t _AlignSize>
712 modulus = _BSize % _AlignSize,
713 value = _BSize + (modulus ? _AlignSize - (modulus) : 0)
719 char __M_unused[aligned_size<
sizeof(value_type),
727 typedef typename _BPVector::iterator _BPiter;
729 template<
typename _Predicate>
731 _S_find(_Predicate __p)
733 _BPiter __first = _S_mem_blocks.begin();
734 while (__first != _S_mem_blocks.end() && !__p(*__first))
739 #if defined _GLIBCXX_DEBUG
743 _S_check_for_free_blocks()
throw()
746 _BPiter __bpi = _S_find(_FFF());
748 _GLIBCXX_DEBUG_ASSERT(__bpi == _S_mem_blocks.end());
767 #if defined _GLIBCXX_DEBUG
768 _S_check_for_free_blocks();
772 / size_t(__detail::bits_per_block));
773 const size_t __size_to_allocate =
sizeof(size_t)
774 + _S_block_size *
sizeof(_Alloc_block)
778 reinterpret_cast<size_t*
>(this->
_M_get(__size_to_allocate));
784 std::make_pair(
reinterpret_cast<_Alloc_block*
>
786 reinterpret_cast<_Alloc_block*
>
788 + _S_block_size - 1);
791 _S_mem_blocks.push_back(__bp);
794 __temp[__i] = ~
static_cast<size_t>(0);
800 static std::size_t _S_block_size;
802 static typename _BPVector::size_type _S_last_dealloc_index;
803 #if defined __GTHREADS
804 static __mutex_type _S_mut;
826 #if defined __GTHREADS
843 while (_S_last_request._M_finished() ==
false
844 && (*(_S_last_request._M_get()) == 0))
845 _S_last_request.operator++();
847 if (__builtin_expect(_S_last_request._M_finished() ==
true,
false))
852 _BPiter __bpi = _S_find(__detail::_Functor_Ref<_FFF>(__fff));
854 if (__bpi != _S_mem_blocks.end())
862 _S_last_request._M_reset(__bpi - _S_mem_blocks.begin());
865 pointer __ret =
reinterpret_cast<pointer
>
866 (__bpi->first + __fff._M_offset() + __nz_bit);
867 size_t* __puse_count =
868 reinterpret_cast<size_t*
>
882 _S_last_request._M_reset(_S_mem_blocks.size() - 1);
893 pointer __ret =
reinterpret_cast<pointer
>
894 (_S_last_request._M_base() + _S_last_request._M_offset() + __nz_bit);
896 size_t* __puse_count =
reinterpret_cast<size_t*
>
897 (_S_mem_blocks[_S_last_request._M_where()].first)
899 __num_bitmaps(_S_mem_blocks[_S_last_request._M_where()]) + 1);
917 #if defined __GTHREADS
920 _Alloc_block* __real_p =
reinterpret_cast<_Alloc_block*
>(__p);
922 typedef typename _BPVector::iterator _Iterator;
923 typedef typename _BPVector::difference_type _Difference_type;
925 _Difference_type __diff;
928 _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index >= 0);
930 __detail::_Inclusive_between<_Alloc_block*> __ibt(__real_p);
931 if (__ibt(_S_mem_blocks[_S_last_dealloc_index]))
933 _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index
934 <= _S_mem_blocks.size() - 1);
937 __diff = _S_last_dealloc_index;
938 __displacement = __real_p - _S_mem_blocks[__diff].first;
942 _Iterator _iter = _S_find(__ibt);
944 _GLIBCXX_DEBUG_ASSERT(_iter != _S_mem_blocks.end());
946 __diff = _iter - _S_mem_blocks.begin();
947 __displacement = __real_p - _S_mem_blocks[__diff].first;
948 _S_last_dealloc_index = __diff;
952 const size_t __rotate = (__displacement
953 % size_t(__detail::bits_per_block));
955 reinterpret_cast<size_t*
>
956 (_S_mem_blocks[__diff].first) - 1;
957 __bitmapC -= (__displacement / size_t(__detail::bits_per_block));
960 size_t* __puse_count =
reinterpret_cast<size_t*
>
961 (_S_mem_blocks[__diff].first)
964 _GLIBCXX_DEBUG_ASSERT(*__puse_count != 0);
968 if (__builtin_expect(*__puse_count == 0,
false))
975 _S_mem_blocks.erase(_S_mem_blocks.begin() + __diff);
983 if ((_Difference_type)_S_last_request._M_where() >= __diff--)
984 _S_last_request._M_reset(__diff);
991 if (_S_last_dealloc_index >= _S_mem_blocks.size())
993 _S_last_dealloc_index =(__diff != -1 ? __diff : 0);
994 _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index >= 0);
1003 bitmap_allocator(
const bitmap_allocator&) _GLIBCXX_USE_NOEXCEPT
1006 template<
typename _Tp1>
1007 bitmap_allocator(
const bitmap_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT
1010 ~bitmap_allocator() _GLIBCXX_USE_NOEXCEPT
1013 _GLIBCXX_NODISCARD pointer
1014 allocate(size_type __n)
1016 if (__n > this->max_size())
1017 std::__throw_bad_alloc();
1019 #if __cpp_aligned_new
1020 if (
alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
1022 const size_type __b = __n *
sizeof(value_type);
1023 std::align_val_t __al = std::align_val_t(
alignof(value_type));
1024 return static_cast<pointer
>(::operator
new(__b, __al));
1028 if (__builtin_expect(__n == 1,
true))
1032 const size_type __b = __n *
sizeof(value_type);
1033 return reinterpret_cast<pointer
>(::operator
new(__b));
1037 _GLIBCXX_NODISCARD pointer
1038 allocate(size_type __n,
typename bitmap_allocator<void>::const_pointer)
1039 {
return allocate(__n); }
1042 deallocate(pointer __p, size_type __n)
throw()
1044 if (__builtin_expect(__p != 0,
true))
1046 #if __cpp_aligned_new
1048 if (
alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
1050 ::operator
delete(__p, std::align_val_t(
alignof(value_type)));
1055 if (__builtin_expect(__n == 1,
true))
1058 ::operator
delete(__p);
1063 address(reference __r)
const _GLIBCXX_NOEXCEPT
1067 address(const_reference __r)
const _GLIBCXX_NOEXCEPT
1071 max_size() const _GLIBCXX_USE_NOEXCEPT
1072 {
return size_type(-1) /
sizeof(value_type); }
1074 #if __cplusplus >= 201103L
1075 template<
typename _Up,
typename... _Args>
1077 construct(_Up* __p, _Args&&... __args)
1078 { ::new((
void *)__p) _Up(std::forward<_Args>(__args)...); }
1080 template<
typename _Up>
1086 construct(pointer __p, const_reference __data)
1087 { ::new((
void *)__p) value_type(__data); }
1090 destroy(pointer __p)
1091 { __p->~value_type(); }
1095 template<
typename _Tp1,
typename _Tp2>
1097 operator==(
const bitmap_allocator<_Tp1>&,
1098 const bitmap_allocator<_Tp2>&)
throw()
1101 #if __cpp_impl_three_way_comparison < 201907L
1102 template<
typename _Tp1,
typename _Tp2>
1104 operator!=(
const bitmap_allocator<_Tp1>&,
1105 const bitmap_allocator<_Tp2>&)
throw()
1110 template<
typename _Tp>
1111 typename bitmap_allocator<_Tp>::_BPVector
1112 bitmap_allocator<_Tp>::_S_mem_blocks;
1114 template<
typename _Tp>
1115 std::size_t bitmap_allocator<_Tp>::_S_block_size
1116 = 2 * std::size_t(__detail::bits_per_block);
1118 template<
typename _Tp>
1119 typename bitmap_allocator<_Tp>::_BPVector::size_type
1120 bitmap_allocator<_Tp>::_S_last_dealloc_index = 0;
1122 template<
typename _Tp>
1123 __detail::_Bitmap_counter
1124 <
typename bitmap_allocator<_Tp>::_Alloc_block*>
1125 bitmap_allocator<_Tp>::_S_last_request(_S_mem_blocks);
1127 #if defined __GTHREADS
1128 template<
typename _Tp>
1129 typename bitmap_allocator<_Tp>::__mutex_type
1130 bitmap_allocator<_Tp>::_S_mut;
1133 _GLIBCXX_END_NAMESPACE_VERSION
#define _BALLOC_ALIGN_BYTES
The constant in the expression below is the alignment required in bytes.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
_Tp * end(valarray< _Tp > &__va) noexcept
Return an iterator pointing to one past the last element of the valarray.
_Tp * begin(valarray< _Tp > &__va) noexcept
Return an iterator pointing to the first element of the valarray.
ISO C++ entities toplevel namespace is std.
GNU extensions for public use.
std::size_t _Bit_scan_forward(std::size_t __num)
Generic Version of the bsf instruction.
void __bit_free(std::size_t *__pbmap, std::size_t __pos)
Mark a memory address as free by setting the corresponding bit in the bit-map.
std::size_t __num_bitmaps(_AddrPair __ap)
The number of Bit-maps pointed to by the address pair passed to the function.
void __bit_allocate(std::size_t *__pbmap, std::size_t __pos)
Mark a memory address as allocated by re-setting the corresponding bit in the bit-map.
std::size_t __num_blocks(_AddrPair __ap)
The number of Blocks pointed to by the address pair passed to the function.
Exception possibly thrown by new.
One of the comparison functors.
One of the comparison functors.
Struct holding two objects of arbitrary type.
_T1 first
The first member.
__mini_vector<> is a stripped down version of the full-fledged std::vector<>.
The class which acts as a predicate for applying the first-fit memory allocation policy for the bitma...
The bitmap counter which acts as the bitmap manipulator, and manages the bit-manipulation functions a...
The free list class for managing chunks of memory to be given to and returned by the bitmap_allocator...
void _M_insert(std::size_t *__addr)
This function returns the block of memory to the internal free list.
void _M_clear()
This function just clears the internal Free List, and gives back all the memory to the OS.
std::size_t * _M_get(std::size_t __sz)
This function gets a block of memory of the specified size from the free list.
Bitmap Allocator, primary template.
pointer _M_allocate_single_object()
Allocates memory for a single object of size sizeof(_Tp).
void _M_deallocate_single_object(pointer __p)
Deallocates memory that belongs to a single object of size sizeof(_Tp).