1f8a1b7d9SAlexander Kabaev // Bitmap Allocator. -*- C++ -*- 2ffeaf689SAlexander Kabaev 3f8a1b7d9SAlexander Kabaev // Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. 4ffeaf689SAlexander Kabaev // 5ffeaf689SAlexander Kabaev // This file is part of the GNU ISO C++ Library. This library is free 6ffeaf689SAlexander Kabaev // software; you can redistribute it and/or modify it under the 7ffeaf689SAlexander Kabaev // terms of the GNU General Public License as published by the 8ffeaf689SAlexander Kabaev // Free Software Foundation; either version 2, or (at your option) 9ffeaf689SAlexander Kabaev // any later version. 10ffeaf689SAlexander Kabaev 11ffeaf689SAlexander Kabaev // This library is distributed in the hope that it will be useful, 12ffeaf689SAlexander Kabaev // but WITHOUT ANY WARRANTY; without even the implied warranty of 13ffeaf689SAlexander Kabaev // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14ffeaf689SAlexander Kabaev // GNU General Public License for more details. 15ffeaf689SAlexander Kabaev 16ffeaf689SAlexander Kabaev // You should have received a copy of the GNU General Public License along 17ffeaf689SAlexander Kabaev // with this library; see the file COPYING. If not, write to the Free 18f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 19ffeaf689SAlexander Kabaev // USA. 20ffeaf689SAlexander Kabaev 21ffeaf689SAlexander Kabaev // As a special exception, you may use this file as part of a free software 22ffeaf689SAlexander Kabaev // library without restriction. Specifically, if other files instantiate 23ffeaf689SAlexander Kabaev // templates or use macros or inline functions from this file, or you compile 24ffeaf689SAlexander Kabaev // this file and link it with other files to produce an executable, this 25ffeaf689SAlexander Kabaev // file does not by itself cause the resulting executable to be covered by 26ffeaf689SAlexander Kabaev // the GNU General Public License. This exception does not however 27ffeaf689SAlexander Kabaev // invalidate any other reasons why the executable file might be covered by 28ffeaf689SAlexander Kabaev // the GNU General Public License. 29ffeaf689SAlexander Kabaev 30f8a1b7d9SAlexander Kabaev /** @file ext/bitmap_allocator.h 31f8a1b7d9SAlexander Kabaev * This file is a GNU extension to the Standard C++ Library. 32f8a1b7d9SAlexander Kabaev */ 33ffeaf689SAlexander Kabaev 34f8a1b7d9SAlexander Kabaev #ifndef _BITMAP_ALLOCATOR_H 35ffeaf689SAlexander Kabaev #define _BITMAP_ALLOCATOR_H 1 36ffeaf689SAlexander Kabaev 37f8a1b7d9SAlexander Kabaev #include <cstddef> // For std::size_t, and ptrdiff_t. 38f8a1b7d9SAlexander Kabaev #include <bits/functexcept.h> // For __throw_bad_alloc(). 39f8a1b7d9SAlexander Kabaev #include <utility> // For std::pair. 40f8a1b7d9SAlexander Kabaev #include <functional> // For greater_equal, and less_equal. 41f8a1b7d9SAlexander Kabaev #include <new> // For operator new. 42f8a1b7d9SAlexander Kabaev #include <debug/debug.h> // _GLIBCXX_DEBUG_ASSERT 43f8a1b7d9SAlexander Kabaev #include <ext/concurrence.h> 44ffeaf689SAlexander Kabaev 45ffeaf689SAlexander Kabaev 46f8a1b7d9SAlexander Kabaev /** @brief The constant in the expression below is the alignment 47f8a1b7d9SAlexander Kabaev * required in bytes. 48f8a1b7d9SAlexander Kabaev */ 49f8a1b7d9SAlexander Kabaev #define _BALLOC_ALIGN_BYTES 8 50ffeaf689SAlexander Kabaev 51f8a1b7d9SAlexander Kabaev _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 52f8a1b7d9SAlexander Kabaev 53f8a1b7d9SAlexander Kabaev using std::size_t; 54f8a1b7d9SAlexander Kabaev using std::ptrdiff_t; 55f8a1b7d9SAlexander Kabaev 56f8a1b7d9SAlexander Kabaev namespace __detail 57ffeaf689SAlexander Kabaev { 58f8a1b7d9SAlexander Kabaev /** @class __mini_vector bitmap_allocator.h bitmap_allocator.h 59f8a1b7d9SAlexander Kabaev * 60f8a1b7d9SAlexander Kabaev * @brief __mini_vector<> is a stripped down version of the 61f8a1b7d9SAlexander Kabaev * full-fledged std::vector<>. 62f8a1b7d9SAlexander Kabaev * 63f8a1b7d9SAlexander Kabaev * It is to be used only for built-in types or PODs. Notable 64f8a1b7d9SAlexander Kabaev * differences are: 65f8a1b7d9SAlexander Kabaev * 66f8a1b7d9SAlexander Kabaev * @detail 67f8a1b7d9SAlexander Kabaev * 1. Not all accessor functions are present. 68f8a1b7d9SAlexander Kabaev * 2. Used ONLY for PODs. 69f8a1b7d9SAlexander Kabaev * 3. No Allocator template argument. Uses ::operator new() to get 70f8a1b7d9SAlexander Kabaev * memory, and ::operator delete() to free it. 71f8a1b7d9SAlexander Kabaev * Caveat: The dtor does NOT free the memory allocated, so this a 72f8a1b7d9SAlexander Kabaev * memory-leaking vector! 73f8a1b7d9SAlexander Kabaev */ 74ffeaf689SAlexander Kabaev template<typename _Tp> 75f8a1b7d9SAlexander Kabaev class __mini_vector 76f8a1b7d9SAlexander Kabaev { 77f8a1b7d9SAlexander Kabaev __mini_vector(const __mini_vector&); 78f8a1b7d9SAlexander Kabaev __mini_vector& operator=(const __mini_vector&); 79f8a1b7d9SAlexander Kabaev 80f8a1b7d9SAlexander Kabaev public: 81f8a1b7d9SAlexander Kabaev typedef _Tp value_type; 82f8a1b7d9SAlexander Kabaev typedef _Tp* pointer; 83f8a1b7d9SAlexander Kabaev typedef _Tp& reference; 84f8a1b7d9SAlexander Kabaev typedef const _Tp& const_reference; 85f8a1b7d9SAlexander Kabaev typedef size_t size_type; 86f8a1b7d9SAlexander Kabaev typedef ptrdiff_t difference_type; 87f8a1b7d9SAlexander Kabaev typedef pointer iterator; 88f8a1b7d9SAlexander Kabaev 89f8a1b7d9SAlexander Kabaev private: 90f8a1b7d9SAlexander Kabaev pointer _M_start; 91f8a1b7d9SAlexander Kabaev pointer _M_finish; 92f8a1b7d9SAlexander Kabaev pointer _M_end_of_storage; 93f8a1b7d9SAlexander Kabaev 94f8a1b7d9SAlexander Kabaev size_type _M_space_left()95f8a1b7d9SAlexander Kabaev _M_space_left() const throw() 96f8a1b7d9SAlexander Kabaev { return _M_end_of_storage - _M_finish; } 97f8a1b7d9SAlexander Kabaev 98f8a1b7d9SAlexander Kabaev pointer allocate(size_type __n)99f8a1b7d9SAlexander Kabaev allocate(size_type __n) 100f8a1b7d9SAlexander Kabaev { return static_cast<pointer>(::operator new(__n * sizeof(_Tp))); } 101f8a1b7d9SAlexander Kabaev 102f8a1b7d9SAlexander Kabaev void deallocate(pointer __p,size_type)103f8a1b7d9SAlexander Kabaev deallocate(pointer __p, size_type) 104f8a1b7d9SAlexander Kabaev { ::operator delete(__p); } 105f8a1b7d9SAlexander Kabaev 106f8a1b7d9SAlexander Kabaev public: 107f8a1b7d9SAlexander Kabaev // Members used: size(), push_back(), pop_back(), 108f8a1b7d9SAlexander Kabaev // insert(iterator, const_reference), erase(iterator), 109f8a1b7d9SAlexander Kabaev // begin(), end(), back(), operator[]. 110f8a1b7d9SAlexander Kabaev __mini_vector()111f8a1b7d9SAlexander Kabaev __mini_vector() : _M_start(0), _M_finish(0), 112f8a1b7d9SAlexander Kabaev _M_end_of_storage(0) 113f8a1b7d9SAlexander Kabaev { } 114f8a1b7d9SAlexander Kabaev 115f8a1b7d9SAlexander Kabaev #if 0 ~__mini_vector()116f8a1b7d9SAlexander Kabaev ~__mini_vector() 117f8a1b7d9SAlexander Kabaev { 118f8a1b7d9SAlexander Kabaev if (this->_M_start) 119f8a1b7d9SAlexander Kabaev { 120f8a1b7d9SAlexander Kabaev this->deallocate(this->_M_start, this->_M_end_of_storage 121f8a1b7d9SAlexander Kabaev - this->_M_start); 122f8a1b7d9SAlexander Kabaev } 123f8a1b7d9SAlexander Kabaev } 124f8a1b7d9SAlexander Kabaev #endif 125f8a1b7d9SAlexander Kabaev 126f8a1b7d9SAlexander Kabaev size_type size()127f8a1b7d9SAlexander Kabaev size() const throw() 128f8a1b7d9SAlexander Kabaev { return _M_finish - _M_start; } 129f8a1b7d9SAlexander Kabaev 130f8a1b7d9SAlexander Kabaev iterator begin()131f8a1b7d9SAlexander Kabaev begin() const throw() 132f8a1b7d9SAlexander Kabaev { return this->_M_start; } 133f8a1b7d9SAlexander Kabaev 134f8a1b7d9SAlexander Kabaev iterator end()135f8a1b7d9SAlexander Kabaev end() const throw() 136f8a1b7d9SAlexander Kabaev { return this->_M_finish; } 137f8a1b7d9SAlexander Kabaev 138f8a1b7d9SAlexander Kabaev reference back()139f8a1b7d9SAlexander Kabaev back() const throw() 140f8a1b7d9SAlexander Kabaev { return *(this->end() - 1); } 141f8a1b7d9SAlexander Kabaev 142f8a1b7d9SAlexander Kabaev reference throw()143f8a1b7d9SAlexander Kabaev operator[](const size_type __pos) const throw() 144f8a1b7d9SAlexander Kabaev { return this->_M_start[__pos]; } 145f8a1b7d9SAlexander Kabaev 146f8a1b7d9SAlexander Kabaev void 147f8a1b7d9SAlexander Kabaev insert(iterator __pos, const_reference __x); 148f8a1b7d9SAlexander Kabaev 149f8a1b7d9SAlexander Kabaev void push_back(const_reference __x)150f8a1b7d9SAlexander Kabaev push_back(const_reference __x) 151f8a1b7d9SAlexander Kabaev { 152f8a1b7d9SAlexander Kabaev if (this->_M_space_left()) 153f8a1b7d9SAlexander Kabaev { 154f8a1b7d9SAlexander Kabaev *this->end() = __x; 155f8a1b7d9SAlexander Kabaev ++this->_M_finish; 156f8a1b7d9SAlexander Kabaev } 157f8a1b7d9SAlexander Kabaev else 158f8a1b7d9SAlexander Kabaev this->insert(this->end(), __x); 159f8a1b7d9SAlexander Kabaev } 160f8a1b7d9SAlexander Kabaev 161f8a1b7d9SAlexander Kabaev void pop_back()162f8a1b7d9SAlexander Kabaev pop_back() throw() 163f8a1b7d9SAlexander Kabaev { --this->_M_finish; } 164f8a1b7d9SAlexander Kabaev 165f8a1b7d9SAlexander Kabaev void 166f8a1b7d9SAlexander Kabaev erase(iterator __pos) throw(); 167f8a1b7d9SAlexander Kabaev 168f8a1b7d9SAlexander Kabaev void clear()169f8a1b7d9SAlexander Kabaev clear() throw() 170f8a1b7d9SAlexander Kabaev { this->_M_finish = this->_M_start; } 171f8a1b7d9SAlexander Kabaev }; 172f8a1b7d9SAlexander Kabaev 173f8a1b7d9SAlexander Kabaev // Out of line function definitions. 174f8a1b7d9SAlexander Kabaev template<typename _Tp> 175f8a1b7d9SAlexander Kabaev void __mini_vector<_Tp>:: insert(iterator __pos,const_reference __x)176f8a1b7d9SAlexander Kabaev insert(iterator __pos, const_reference __x) 177f8a1b7d9SAlexander Kabaev { 178f8a1b7d9SAlexander Kabaev if (this->_M_space_left()) 179f8a1b7d9SAlexander Kabaev { 180f8a1b7d9SAlexander Kabaev size_type __to_move = this->_M_finish - __pos; 181f8a1b7d9SAlexander Kabaev iterator __dest = this->end(); 182f8a1b7d9SAlexander Kabaev iterator __src = this->end() - 1; 183f8a1b7d9SAlexander Kabaev 184f8a1b7d9SAlexander Kabaev ++this->_M_finish; 185f8a1b7d9SAlexander Kabaev while (__to_move) 186f8a1b7d9SAlexander Kabaev { 187f8a1b7d9SAlexander Kabaev *__dest = *__src; 188f8a1b7d9SAlexander Kabaev --__dest; --__src; --__to_move; 189f8a1b7d9SAlexander Kabaev } 190f8a1b7d9SAlexander Kabaev *__pos = __x; 191f8a1b7d9SAlexander Kabaev } 192f8a1b7d9SAlexander Kabaev else 193f8a1b7d9SAlexander Kabaev { 194f8a1b7d9SAlexander Kabaev size_type __new_size = this->size() ? this->size() * 2 : 1; 195f8a1b7d9SAlexander Kabaev iterator __new_start = this->allocate(__new_size); 196f8a1b7d9SAlexander Kabaev iterator __first = this->begin(); 197f8a1b7d9SAlexander Kabaev iterator __start = __new_start; 198f8a1b7d9SAlexander Kabaev while (__first != __pos) 199f8a1b7d9SAlexander Kabaev { 200f8a1b7d9SAlexander Kabaev *__start = *__first; 201f8a1b7d9SAlexander Kabaev ++__start; ++__first; 202f8a1b7d9SAlexander Kabaev } 203f8a1b7d9SAlexander Kabaev *__start = __x; 204f8a1b7d9SAlexander Kabaev ++__start; 205f8a1b7d9SAlexander Kabaev while (__first != this->end()) 206f8a1b7d9SAlexander Kabaev { 207f8a1b7d9SAlexander Kabaev *__start = *__first; 208f8a1b7d9SAlexander Kabaev ++__start; ++__first; 209f8a1b7d9SAlexander Kabaev } 210f8a1b7d9SAlexander Kabaev if (this->_M_start) 211f8a1b7d9SAlexander Kabaev this->deallocate(this->_M_start, this->size()); 212f8a1b7d9SAlexander Kabaev 213f8a1b7d9SAlexander Kabaev this->_M_start = __new_start; 214f8a1b7d9SAlexander Kabaev this->_M_finish = __start; 215f8a1b7d9SAlexander Kabaev this->_M_end_of_storage = this->_M_start + __new_size; 216f8a1b7d9SAlexander Kabaev } 217f8a1b7d9SAlexander Kabaev } 218f8a1b7d9SAlexander Kabaev 219f8a1b7d9SAlexander Kabaev template<typename _Tp> 220f8a1b7d9SAlexander Kabaev void __mini_vector<_Tp>:: erase(iterator __pos)221f8a1b7d9SAlexander Kabaev erase(iterator __pos) throw() 222f8a1b7d9SAlexander Kabaev { 223f8a1b7d9SAlexander Kabaev while (__pos + 1 != this->end()) 224f8a1b7d9SAlexander Kabaev { 225f8a1b7d9SAlexander Kabaev *__pos = __pos[1]; 226f8a1b7d9SAlexander Kabaev ++__pos; 227f8a1b7d9SAlexander Kabaev } 228f8a1b7d9SAlexander Kabaev --this->_M_finish; 229f8a1b7d9SAlexander Kabaev } 230f8a1b7d9SAlexander Kabaev 231f8a1b7d9SAlexander Kabaev 232f8a1b7d9SAlexander Kabaev template<typename _Tp> 233f8a1b7d9SAlexander Kabaev struct __mv_iter_traits 234f8a1b7d9SAlexander Kabaev { 235f8a1b7d9SAlexander Kabaev typedef typename _Tp::value_type value_type; 236f8a1b7d9SAlexander Kabaev typedef typename _Tp::difference_type difference_type; 237f8a1b7d9SAlexander Kabaev }; 238f8a1b7d9SAlexander Kabaev 239f8a1b7d9SAlexander Kabaev template<typename _Tp> 240f8a1b7d9SAlexander Kabaev struct __mv_iter_traits<_Tp*> 241f8a1b7d9SAlexander Kabaev { 242f8a1b7d9SAlexander Kabaev typedef _Tp value_type; 243f8a1b7d9SAlexander Kabaev typedef ptrdiff_t difference_type; 244f8a1b7d9SAlexander Kabaev }; 245f8a1b7d9SAlexander Kabaev 246f8a1b7d9SAlexander Kabaev enum 247f8a1b7d9SAlexander Kabaev { 248f8a1b7d9SAlexander Kabaev bits_per_byte = 8, 249f8a1b7d9SAlexander Kabaev bits_per_block = sizeof(size_t) * size_t(bits_per_byte) 250f8a1b7d9SAlexander Kabaev }; 251f8a1b7d9SAlexander Kabaev 252f8a1b7d9SAlexander Kabaev template<typename _ForwardIterator, typename _Tp, typename _Compare> 253f8a1b7d9SAlexander Kabaev _ForwardIterator 254f8a1b7d9SAlexander Kabaev __lower_bound(_ForwardIterator __first, _ForwardIterator __last, 255f8a1b7d9SAlexander Kabaev const _Tp& __val, _Compare __comp) 256f8a1b7d9SAlexander Kabaev { 257f8a1b7d9SAlexander Kabaev typedef typename __mv_iter_traits<_ForwardIterator>::value_type 258f8a1b7d9SAlexander Kabaev _ValueType; 259f8a1b7d9SAlexander Kabaev typedef typename __mv_iter_traits<_ForwardIterator>::difference_type 260f8a1b7d9SAlexander Kabaev _DistanceType; 261f8a1b7d9SAlexander Kabaev 262f8a1b7d9SAlexander Kabaev _DistanceType __len = __last - __first; 263f8a1b7d9SAlexander Kabaev _DistanceType __half; 264f8a1b7d9SAlexander Kabaev _ForwardIterator __middle; 265f8a1b7d9SAlexander Kabaev 266f8a1b7d9SAlexander Kabaev while (__len > 0) 267f8a1b7d9SAlexander Kabaev { 268f8a1b7d9SAlexander Kabaev __half = __len >> 1; 269f8a1b7d9SAlexander Kabaev __middle = __first; 270f8a1b7d9SAlexander Kabaev __middle += __half; 271f8a1b7d9SAlexander Kabaev if (__comp(*__middle, __val)) 272f8a1b7d9SAlexander Kabaev { 273f8a1b7d9SAlexander Kabaev __first = __middle; 274f8a1b7d9SAlexander Kabaev ++__first; 275f8a1b7d9SAlexander Kabaev __len = __len - __half - 1; 276f8a1b7d9SAlexander Kabaev } 277f8a1b7d9SAlexander Kabaev else 278f8a1b7d9SAlexander Kabaev __len = __half; 279f8a1b7d9SAlexander Kabaev } 280f8a1b7d9SAlexander Kabaev return __first; 281f8a1b7d9SAlexander Kabaev } 282f8a1b7d9SAlexander Kabaev 283f8a1b7d9SAlexander Kabaev template<typename _InputIterator, typename _Predicate> 284f8a1b7d9SAlexander Kabaev inline _InputIterator 285f8a1b7d9SAlexander Kabaev __find_if(_InputIterator __first, _InputIterator __last, _Predicate __p) 286f8a1b7d9SAlexander Kabaev { 287f8a1b7d9SAlexander Kabaev while (__first != __last && !__p(*__first)) 288f8a1b7d9SAlexander Kabaev ++__first; 289f8a1b7d9SAlexander Kabaev return __first; 290f8a1b7d9SAlexander Kabaev } 291f8a1b7d9SAlexander Kabaev 292f8a1b7d9SAlexander Kabaev /** @brief The number of Blocks pointed to by the address pair 293f8a1b7d9SAlexander Kabaev * passed to the function. 294f8a1b7d9SAlexander Kabaev */ 295f8a1b7d9SAlexander Kabaev template<typename _AddrPair> 296f8a1b7d9SAlexander Kabaev inline size_t 297f8a1b7d9SAlexander Kabaev __num_blocks(_AddrPair __ap) 298f8a1b7d9SAlexander Kabaev { return (__ap.second - __ap.first) + 1; } 299f8a1b7d9SAlexander Kabaev 300f8a1b7d9SAlexander Kabaev /** @brief The number of Bit-maps pointed to by the address pair 301f8a1b7d9SAlexander Kabaev * passed to the function. 302f8a1b7d9SAlexander Kabaev */ 303f8a1b7d9SAlexander Kabaev template<typename _AddrPair> 304f8a1b7d9SAlexander Kabaev inline size_t 305f8a1b7d9SAlexander Kabaev __num_bitmaps(_AddrPair __ap) 306f8a1b7d9SAlexander Kabaev { return __num_blocks(__ap) / size_t(bits_per_block); } 307f8a1b7d9SAlexander Kabaev 308f8a1b7d9SAlexander Kabaev // _Tp should be a pointer type. 309f8a1b7d9SAlexander Kabaev template<typename _Tp> 310f8a1b7d9SAlexander Kabaev class _Inclusive_between 311f8a1b7d9SAlexander Kabaev : public std::unary_function<typename std::pair<_Tp, _Tp>, bool> 312f8a1b7d9SAlexander Kabaev { 313ffeaf689SAlexander Kabaev typedef _Tp pointer; 314ffeaf689SAlexander Kabaev pointer _M_ptr_value; 315ffeaf689SAlexander Kabaev typedef typename std::pair<_Tp, _Tp> _Block_pair; 316ffeaf689SAlexander Kabaev 317ffeaf689SAlexander Kabaev public: 318f8a1b7d9SAlexander Kabaev _Inclusive_between(pointer __ptr) : _M_ptr_value(__ptr) 319f8a1b7d9SAlexander Kabaev { } 320f8a1b7d9SAlexander Kabaev 321f8a1b7d9SAlexander Kabaev bool 322f8a1b7d9SAlexander Kabaev operator()(_Block_pair __bp) const throw() 323ffeaf689SAlexander Kabaev { 324f8a1b7d9SAlexander Kabaev if (std::less_equal<pointer>()(_M_ptr_value, __bp.second) 325f8a1b7d9SAlexander Kabaev && std::greater_equal<pointer>()(_M_ptr_value, __bp.first)) 326ffeaf689SAlexander Kabaev return true; 327ffeaf689SAlexander Kabaev else 328ffeaf689SAlexander Kabaev return false; 329ffeaf689SAlexander Kabaev } 330ffeaf689SAlexander Kabaev }; 331ffeaf689SAlexander Kabaev 332ffeaf689SAlexander Kabaev // Used to pass a Functor to functions by reference. 333ffeaf689SAlexander Kabaev template<typename _Functor> 334f8a1b7d9SAlexander Kabaev class _Functor_Ref 335f8a1b7d9SAlexander Kabaev : public std::unary_function<typename _Functor::argument_type, 336f8a1b7d9SAlexander Kabaev typename _Functor::result_type> 337f8a1b7d9SAlexander Kabaev { 338ffeaf689SAlexander Kabaev _Functor& _M_fref; 339ffeaf689SAlexander Kabaev 340ffeaf689SAlexander Kabaev public: 341ffeaf689SAlexander Kabaev typedef typename _Functor::argument_type argument_type; 342ffeaf689SAlexander Kabaev typedef typename _Functor::result_type result_type; 343ffeaf689SAlexander Kabaev 344f8a1b7d9SAlexander Kabaev _Functor_Ref(_Functor& __fref) : _M_fref(__fref) 345ffeaf689SAlexander Kabaev { } 346ffeaf689SAlexander Kabaev 347f8a1b7d9SAlexander Kabaev result_type 348f8a1b7d9SAlexander Kabaev operator()(argument_type __arg) 349f8a1b7d9SAlexander Kabaev { return _M_fref(__arg); } 350f8a1b7d9SAlexander Kabaev }; 351f8a1b7d9SAlexander Kabaev 352f8a1b7d9SAlexander Kabaev /** @class _Ffit_finder bitmap_allocator.h bitmap_allocator.h 353f8a1b7d9SAlexander Kabaev * 354f8a1b7d9SAlexander Kabaev * @brief The class which acts as a predicate for applying the 355f8a1b7d9SAlexander Kabaev * first-fit memory allocation policy for the bitmap allocator. 356f8a1b7d9SAlexander Kabaev */ 357f8a1b7d9SAlexander Kabaev // _Tp should be a pointer type, and _Alloc is the Allocator for 358f8a1b7d9SAlexander Kabaev // the vector. 359f8a1b7d9SAlexander Kabaev template<typename _Tp> 360f8a1b7d9SAlexander Kabaev class _Ffit_finder 361f8a1b7d9SAlexander Kabaev : public std::unary_function<typename std::pair<_Tp, _Tp>, bool> 362ffeaf689SAlexander Kabaev { 363f8a1b7d9SAlexander Kabaev typedef typename std::pair<_Tp, _Tp> _Block_pair; 364f8a1b7d9SAlexander Kabaev typedef typename __detail::__mini_vector<_Block_pair> _BPVector; 365f8a1b7d9SAlexander Kabaev typedef typename _BPVector::difference_type _Counter_type; 366f8a1b7d9SAlexander Kabaev 367f8a1b7d9SAlexander Kabaev size_t* _M_pbitmap; 368f8a1b7d9SAlexander Kabaev _Counter_type _M_data_offset; 369f8a1b7d9SAlexander Kabaev 370f8a1b7d9SAlexander Kabaev public: 371f8a1b7d9SAlexander Kabaev _Ffit_finder() : _M_pbitmap(0), _M_data_offset(0) 372f8a1b7d9SAlexander Kabaev { } 373f8a1b7d9SAlexander Kabaev 374f8a1b7d9SAlexander Kabaev bool 375f8a1b7d9SAlexander Kabaev operator()(_Block_pair __bp) throw() 376f8a1b7d9SAlexander Kabaev { 377f8a1b7d9SAlexander Kabaev // Set the _rover to the last physical location bitmap, 378f8a1b7d9SAlexander Kabaev // which is the bitmap which belongs to the first free 379f8a1b7d9SAlexander Kabaev // block. Thus, the bitmaps are in exact reverse order of 380f8a1b7d9SAlexander Kabaev // the actual memory layout. So, we count down the bimaps, 381f8a1b7d9SAlexander Kabaev // which is the same as moving up the memory. 382ffeaf689SAlexander Kabaev 383ffeaf689SAlexander Kabaev // If the used count stored at the start of the Bit Map headers 384ffeaf689SAlexander Kabaev // is equal to the number of Objects that the current Block can 385ffeaf689SAlexander Kabaev // store, then there is definitely no space for another single 386ffeaf689SAlexander Kabaev // object, so just return false. 387f8a1b7d9SAlexander Kabaev _Counter_type __diff = 388f8a1b7d9SAlexander Kabaev __gnu_cxx::__detail::__num_bitmaps(__bp); 389ffeaf689SAlexander Kabaev 390f8a1b7d9SAlexander Kabaev if (*(reinterpret_cast<size_t*> 391f8a1b7d9SAlexander Kabaev (__bp.first) - (__diff + 1)) 392f8a1b7d9SAlexander Kabaev == __gnu_cxx::__detail::__num_blocks(__bp)) 393ffeaf689SAlexander Kabaev return false; 394ffeaf689SAlexander Kabaev 395f8a1b7d9SAlexander Kabaev size_t* __rover = reinterpret_cast<size_t*>(__bp.first) - 1; 396f8a1b7d9SAlexander Kabaev 397ffeaf689SAlexander Kabaev for (_Counter_type __i = 0; __i < __diff; ++__i) 398ffeaf689SAlexander Kabaev { 399ffeaf689SAlexander Kabaev _M_data_offset = __i; 400ffeaf689SAlexander Kabaev if (*__rover) 401ffeaf689SAlexander Kabaev { 402ffeaf689SAlexander Kabaev _M_pbitmap = __rover; 403ffeaf689SAlexander Kabaev return true; 404ffeaf689SAlexander Kabaev } 405ffeaf689SAlexander Kabaev --__rover; 406ffeaf689SAlexander Kabaev } 407ffeaf689SAlexander Kabaev return false; 408ffeaf689SAlexander Kabaev } 409ffeaf689SAlexander Kabaev 410f8a1b7d9SAlexander Kabaev 411f8a1b7d9SAlexander Kabaev size_t* 412f8a1b7d9SAlexander Kabaev _M_get() const throw() 413f8a1b7d9SAlexander Kabaev { return _M_pbitmap; } 414f8a1b7d9SAlexander Kabaev 415f8a1b7d9SAlexander Kabaev _Counter_type 416f8a1b7d9SAlexander Kabaev _M_offset() const throw() 417f8a1b7d9SAlexander Kabaev { return _M_data_offset * size_t(bits_per_block); } 418ffeaf689SAlexander Kabaev }; 419ffeaf689SAlexander Kabaev 420ffeaf689SAlexander Kabaev 421f8a1b7d9SAlexander Kabaev /** @class _Bitmap_counter bitmap_allocator.h bitmap_allocator.h 422f8a1b7d9SAlexander Kabaev * 423f8a1b7d9SAlexander Kabaev * @brief The bitmap counter which acts as the bitmap 424f8a1b7d9SAlexander Kabaev * manipulator, and manages the bit-manipulation functions and 425f8a1b7d9SAlexander Kabaev * the searching and identification functions on the bit-map. 426f8a1b7d9SAlexander Kabaev */ 427f8a1b7d9SAlexander Kabaev // _Tp should be a pointer type. 428f8a1b7d9SAlexander Kabaev template<typename _Tp> 429f8a1b7d9SAlexander Kabaev class _Bitmap_counter 430f8a1b7d9SAlexander Kabaev { 431f8a1b7d9SAlexander Kabaev typedef typename __detail::__mini_vector<typename std::pair<_Tp, _Tp> > 432f8a1b7d9SAlexander Kabaev _BPVector; 433ffeaf689SAlexander Kabaev typedef typename _BPVector::size_type _Index_type; 434ffeaf689SAlexander Kabaev typedef _Tp pointer; 435ffeaf689SAlexander Kabaev 436ffeaf689SAlexander Kabaev _BPVector& _M_vbp; 437f8a1b7d9SAlexander Kabaev size_t* _M_curr_bmap; 438f8a1b7d9SAlexander Kabaev size_t* _M_last_bmap_in_block; 439ffeaf689SAlexander Kabaev _Index_type _M_curr_index; 440ffeaf689SAlexander Kabaev 441ffeaf689SAlexander Kabaev public: 442f8a1b7d9SAlexander Kabaev // Use the 2nd parameter with care. Make sure that such an 443f8a1b7d9SAlexander Kabaev // entry exists in the vector before passing that particular 444f8a1b7d9SAlexander Kabaev // index to this ctor. 445f8a1b7d9SAlexander Kabaev _Bitmap_counter(_BPVector& Rvbp, long __index = -1) : _M_vbp(Rvbp) 446f8a1b7d9SAlexander Kabaev { this->_M_reset(__index); } 447ffeaf689SAlexander Kabaev 448f8a1b7d9SAlexander Kabaev void 449f8a1b7d9SAlexander Kabaev _M_reset(long __index = -1) throw() 450ffeaf689SAlexander Kabaev { 451ffeaf689SAlexander Kabaev if (__index == -1) 452ffeaf689SAlexander Kabaev { 453ffeaf689SAlexander Kabaev _M_curr_bmap = 0; 454f8a1b7d9SAlexander Kabaev _M_curr_index = static_cast<_Index_type>(-1); 455ffeaf689SAlexander Kabaev return; 456ffeaf689SAlexander Kabaev } 457ffeaf689SAlexander Kabaev 458ffeaf689SAlexander Kabaev _M_curr_index = __index; 459f8a1b7d9SAlexander Kabaev _M_curr_bmap = reinterpret_cast<size_t*> 460f8a1b7d9SAlexander Kabaev (_M_vbp[_M_curr_index].first) - 1; 461ffeaf689SAlexander Kabaev 462f8a1b7d9SAlexander Kabaev _GLIBCXX_DEBUG_ASSERT(__index <= (long)_M_vbp.size() - 1); 463ffeaf689SAlexander Kabaev 464f8a1b7d9SAlexander Kabaev _M_last_bmap_in_block = _M_curr_bmap 465f8a1b7d9SAlexander Kabaev - ((_M_vbp[_M_curr_index].second 466f8a1b7d9SAlexander Kabaev - _M_vbp[_M_curr_index].first + 1) 467f8a1b7d9SAlexander Kabaev / size_t(bits_per_block) - 1); 468ffeaf689SAlexander Kabaev } 469ffeaf689SAlexander Kabaev 470ffeaf689SAlexander Kabaev // Dangerous Function! Use with extreme care. Pass to this 471ffeaf689SAlexander Kabaev // function ONLY those values that are known to be correct, 472ffeaf689SAlexander Kabaev // otherwise this will mess up big time. 473f8a1b7d9SAlexander Kabaev void 474f8a1b7d9SAlexander Kabaev _M_set_internal_bitmap(size_t* __new_internal_marker) throw() 475f8a1b7d9SAlexander Kabaev { _M_curr_bmap = __new_internal_marker; } 476ffeaf689SAlexander Kabaev 477f8a1b7d9SAlexander Kabaev bool 478f8a1b7d9SAlexander Kabaev _M_finished() const throw() 479f8a1b7d9SAlexander Kabaev { return(_M_curr_bmap == 0); } 480ffeaf689SAlexander Kabaev 481f8a1b7d9SAlexander Kabaev _Bitmap_counter& 482f8a1b7d9SAlexander Kabaev operator++() throw() 483ffeaf689SAlexander Kabaev { 484ffeaf689SAlexander Kabaev if (_M_curr_bmap == _M_last_bmap_in_block) 485ffeaf689SAlexander Kabaev { 486ffeaf689SAlexander Kabaev if (++_M_curr_index == _M_vbp.size()) 487ffeaf689SAlexander Kabaev _M_curr_bmap = 0; 488ffeaf689SAlexander Kabaev else 489ffeaf689SAlexander Kabaev this->_M_reset(_M_curr_index); 490ffeaf689SAlexander Kabaev } 491ffeaf689SAlexander Kabaev else 492ffeaf689SAlexander Kabaev --_M_curr_bmap; 493ffeaf689SAlexander Kabaev return *this; 494ffeaf689SAlexander Kabaev } 495ffeaf689SAlexander Kabaev 496f8a1b7d9SAlexander Kabaev size_t* 497f8a1b7d9SAlexander Kabaev _M_get() const throw() 498f8a1b7d9SAlexander Kabaev { return _M_curr_bmap; } 499f8a1b7d9SAlexander Kabaev 500f8a1b7d9SAlexander Kabaev pointer 501f8a1b7d9SAlexander Kabaev _M_base() const throw() 502f8a1b7d9SAlexander Kabaev { return _M_vbp[_M_curr_index].first; } 503f8a1b7d9SAlexander Kabaev 504f8a1b7d9SAlexander Kabaev _Index_type 505f8a1b7d9SAlexander Kabaev _M_offset() const throw() 506ffeaf689SAlexander Kabaev { 507f8a1b7d9SAlexander Kabaev return size_t(bits_per_block) 508f8a1b7d9SAlexander Kabaev * ((reinterpret_cast<size_t*>(this->_M_base()) 509f8a1b7d9SAlexander Kabaev - _M_curr_bmap) - 1); 510ffeaf689SAlexander Kabaev } 511ffeaf689SAlexander Kabaev 512f8a1b7d9SAlexander Kabaev _Index_type 513f8a1b7d9SAlexander Kabaev _M_where() const throw() 514f8a1b7d9SAlexander Kabaev { return _M_curr_index; } 515ffeaf689SAlexander Kabaev }; 516ffeaf689SAlexander Kabaev 517f8a1b7d9SAlexander Kabaev /** @brief Mark a memory address as allocated by re-setting the 518f8a1b7d9SAlexander Kabaev * corresponding bit in the bit-map. 519f8a1b7d9SAlexander Kabaev */ 520f8a1b7d9SAlexander Kabaev inline void 521f8a1b7d9SAlexander Kabaev __bit_allocate(size_t* __pbmap, size_t __pos) throw() 522ffeaf689SAlexander Kabaev { 523f8a1b7d9SAlexander Kabaev size_t __mask = 1 << __pos; 524f8a1b7d9SAlexander Kabaev __mask = ~__mask; 525f8a1b7d9SAlexander Kabaev *__pbmap &= __mask; 526ffeaf689SAlexander Kabaev } 527f8a1b7d9SAlexander Kabaev 528f8a1b7d9SAlexander Kabaev /** @brief Mark a memory address as free by setting the 529f8a1b7d9SAlexander Kabaev * corresponding bit in the bit-map. 530f8a1b7d9SAlexander Kabaev */ 531f8a1b7d9SAlexander Kabaev inline void 532f8a1b7d9SAlexander Kabaev __bit_free(size_t* __pbmap, size_t __pos) throw() 533f8a1b7d9SAlexander Kabaev { 534f8a1b7d9SAlexander Kabaev size_t __mask = 1 << __pos; 535f8a1b7d9SAlexander Kabaev *__pbmap |= __mask; 536f8a1b7d9SAlexander Kabaev } 537f8a1b7d9SAlexander Kabaev } // namespace __detail 538f8a1b7d9SAlexander Kabaev 539f8a1b7d9SAlexander Kabaev /** @brief Generic Version of the bsf instruction. 540f8a1b7d9SAlexander Kabaev */ 541f8a1b7d9SAlexander Kabaev inline size_t 542f8a1b7d9SAlexander Kabaev _Bit_scan_forward(size_t __num) 543f8a1b7d9SAlexander Kabaev { return static_cast<size_t>(__builtin_ctzl(__num)); } 544f8a1b7d9SAlexander Kabaev 545f8a1b7d9SAlexander Kabaev /** @class free_list bitmap_allocator.h bitmap_allocator.h 546f8a1b7d9SAlexander Kabaev * 547f8a1b7d9SAlexander Kabaev * @brief The free list class for managing chunks of memory to be 548f8a1b7d9SAlexander Kabaev * given to and returned by the bitmap_allocator. 549f8a1b7d9SAlexander Kabaev */ 550f8a1b7d9SAlexander Kabaev class free_list 551f8a1b7d9SAlexander Kabaev { 552*1fdc87e7SRui Paulo public: 553f8a1b7d9SAlexander Kabaev typedef size_t* value_type; 554f8a1b7d9SAlexander Kabaev typedef __detail::__mini_vector<value_type> vector_type; 555f8a1b7d9SAlexander Kabaev typedef vector_type::iterator iterator; 556f8a1b7d9SAlexander Kabaev typedef __mutex __mutex_type; 557f8a1b7d9SAlexander Kabaev 558*1fdc87e7SRui Paulo private: 559f8a1b7d9SAlexander Kabaev struct _LT_pointer_compare 560f8a1b7d9SAlexander Kabaev { 561f8a1b7d9SAlexander Kabaev bool 562f8a1b7d9SAlexander Kabaev operator()(const size_t* __pui, 563f8a1b7d9SAlexander Kabaev const size_t __cui) const throw() 564f8a1b7d9SAlexander Kabaev { return *__pui < __cui; } 565ffeaf689SAlexander Kabaev }; 566ffeaf689SAlexander Kabaev 567ffeaf689SAlexander Kabaev #if defined __GTHREADS 568f8a1b7d9SAlexander Kabaev __mutex_type& 569f8a1b7d9SAlexander Kabaev _M_get_mutex() 570f8a1b7d9SAlexander Kabaev { 571f8a1b7d9SAlexander Kabaev static __mutex_type _S_mutex; 572f8a1b7d9SAlexander Kabaev return _S_mutex; 573f8a1b7d9SAlexander Kabaev } 574ffeaf689SAlexander Kabaev #endif 575ffeaf689SAlexander Kabaev 576f8a1b7d9SAlexander Kabaev vector_type& 577f8a1b7d9SAlexander Kabaev _M_get_free_list() 578ffeaf689SAlexander Kabaev { 579f8a1b7d9SAlexander Kabaev static vector_type _S_free_list; 580f8a1b7d9SAlexander Kabaev return _S_free_list; 581f8a1b7d9SAlexander Kabaev } 582f8a1b7d9SAlexander Kabaev 583f8a1b7d9SAlexander Kabaev /** @brief Performs validation of memory based on their size. 584f8a1b7d9SAlexander Kabaev * 585f8a1b7d9SAlexander Kabaev * @param __addr The pointer to the memory block to be 586f8a1b7d9SAlexander Kabaev * validated. 587f8a1b7d9SAlexander Kabaev * 588f8a1b7d9SAlexander Kabaev * @detail Validates the memory block passed to this function and 589f8a1b7d9SAlexander Kabaev * appropriately performs the action of managing the free list of 590f8a1b7d9SAlexander Kabaev * blocks by adding this block to the free list or deleting this 591f8a1b7d9SAlexander Kabaev * or larger blocks from the free list. 592f8a1b7d9SAlexander Kabaev */ 593f8a1b7d9SAlexander Kabaev void 594f8a1b7d9SAlexander Kabaev _M_validate(size_t* __addr) throw() 595ffeaf689SAlexander Kabaev { 596f8a1b7d9SAlexander Kabaev vector_type& __free_list = _M_get_free_list(); 597f8a1b7d9SAlexander Kabaev const vector_type::size_type __max_size = 64; 598f8a1b7d9SAlexander Kabaev if (__free_list.size() >= __max_size) 599ffeaf689SAlexander Kabaev { 600f8a1b7d9SAlexander Kabaev // Ok, the threshold value has been reached. We determine 601f8a1b7d9SAlexander Kabaev // which block to remove from the list of free blocks. 602f8a1b7d9SAlexander Kabaev if (*__addr >= *__free_list.back()) 603f8a1b7d9SAlexander Kabaev { 604f8a1b7d9SAlexander Kabaev // Ok, the new block is greater than or equal to the 605f8a1b7d9SAlexander Kabaev // last block in the list of free blocks. We just free 606f8a1b7d9SAlexander Kabaev // the new block. 607f8a1b7d9SAlexander Kabaev ::operator delete(static_cast<void*>(__addr)); 608ffeaf689SAlexander Kabaev return; 609ffeaf689SAlexander Kabaev } 610ffeaf689SAlexander Kabaev else 611ffeaf689SAlexander Kabaev { 612f8a1b7d9SAlexander Kabaev // Deallocate the last block in the list of free lists, 613f8a1b7d9SAlexander Kabaev // and insert the new one in it's correct position. 614f8a1b7d9SAlexander Kabaev ::operator delete(static_cast<void*>(__free_list.back())); 615f8a1b7d9SAlexander Kabaev __free_list.pop_back(); 616ffeaf689SAlexander Kabaev } 617ffeaf689SAlexander Kabaev } 618ffeaf689SAlexander Kabaev 619f8a1b7d9SAlexander Kabaev // Just add the block to the list of free lists unconditionally. 620f8a1b7d9SAlexander Kabaev iterator __temp = __gnu_cxx::__detail::__lower_bound 621f8a1b7d9SAlexander Kabaev (__free_list.begin(), __free_list.end(), 622ffeaf689SAlexander Kabaev *__addr, _LT_pointer_compare()); 623f8a1b7d9SAlexander Kabaev 624ffeaf689SAlexander Kabaev // We may insert the new free list before _temp; 625f8a1b7d9SAlexander Kabaev __free_list.insert(__temp, __addr); 626ffeaf689SAlexander Kabaev } 627ffeaf689SAlexander Kabaev 628f8a1b7d9SAlexander Kabaev /** @brief Decides whether the wastage of memory is acceptable for 629f8a1b7d9SAlexander Kabaev * the current memory request and returns accordingly. 630f8a1b7d9SAlexander Kabaev * 631f8a1b7d9SAlexander Kabaev * @param __block_size The size of the block available in the free 632f8a1b7d9SAlexander Kabaev * list. 633f8a1b7d9SAlexander Kabaev * 634f8a1b7d9SAlexander Kabaev * @param __required_size The required size of the memory block. 635f8a1b7d9SAlexander Kabaev * 636f8a1b7d9SAlexander Kabaev * @return true if the wastage incurred is acceptable, else returns 637f8a1b7d9SAlexander Kabaev * false. 638f8a1b7d9SAlexander Kabaev */ 639f8a1b7d9SAlexander Kabaev bool 640f8a1b7d9SAlexander Kabaev _M_should_i_give(size_t __block_size, 641f8a1b7d9SAlexander Kabaev size_t __required_size) throw() 642ffeaf689SAlexander Kabaev { 643f8a1b7d9SAlexander Kabaev const size_t __max_wastage_percentage = 36; 644ffeaf689SAlexander Kabaev if (__block_size >= __required_size && 645f8a1b7d9SAlexander Kabaev (((__block_size - __required_size) * 100 / __block_size) 646f8a1b7d9SAlexander Kabaev < __max_wastage_percentage)) 647ffeaf689SAlexander Kabaev return true; 648ffeaf689SAlexander Kabaev else 649ffeaf689SAlexander Kabaev return false; 650ffeaf689SAlexander Kabaev } 651ffeaf689SAlexander Kabaev 652ffeaf689SAlexander Kabaev public: 653f8a1b7d9SAlexander Kabaev /** @brief This function returns the block of memory to the 654f8a1b7d9SAlexander Kabaev * internal free list. 655f8a1b7d9SAlexander Kabaev * 656f8a1b7d9SAlexander Kabaev * @param __addr The pointer to the memory block that was given 657f8a1b7d9SAlexander Kabaev * by a call to the _M_get function. 658f8a1b7d9SAlexander Kabaev */ 659f8a1b7d9SAlexander Kabaev inline void 660f8a1b7d9SAlexander Kabaev _M_insert(size_t* __addr) throw() 661ffeaf689SAlexander Kabaev { 662ffeaf689SAlexander Kabaev #if defined __GTHREADS 663f8a1b7d9SAlexander Kabaev __gnu_cxx::__scoped_lock __bfl_lock(_M_get_mutex()); 664ffeaf689SAlexander Kabaev #endif 665f8a1b7d9SAlexander Kabaev // Call _M_validate to decide what should be done with 666f8a1b7d9SAlexander Kabaev // this particular free list. 667f8a1b7d9SAlexander Kabaev this->_M_validate(reinterpret_cast<size_t*>(__addr) - 1); 668f8a1b7d9SAlexander Kabaev // See discussion as to why this is 1! 669ffeaf689SAlexander Kabaev } 670ffeaf689SAlexander Kabaev 671f8a1b7d9SAlexander Kabaev /** @brief This function gets a block of memory of the specified 672f8a1b7d9SAlexander Kabaev * size from the free list. 673f8a1b7d9SAlexander Kabaev * 674f8a1b7d9SAlexander Kabaev * @param __sz The size in bytes of the memory required. 675f8a1b7d9SAlexander Kabaev * 676f8a1b7d9SAlexander Kabaev * @return A pointer to the new memory block of size at least 677f8a1b7d9SAlexander Kabaev * equal to that requested. 678f8a1b7d9SAlexander Kabaev */ 679f8a1b7d9SAlexander Kabaev size_t* 680f8a1b7d9SAlexander Kabaev _M_get(size_t __sz) throw(std::bad_alloc); 681ffeaf689SAlexander Kabaev 682f8a1b7d9SAlexander Kabaev /** @brief This function just clears the internal Free List, and 683f8a1b7d9SAlexander Kabaev * gives back all the memory to the OS. 684f8a1b7d9SAlexander Kabaev */ 685f8a1b7d9SAlexander Kabaev void 686f8a1b7d9SAlexander Kabaev _M_clear(); 687ffeaf689SAlexander Kabaev }; 688ffeaf689SAlexander Kabaev 689ffeaf689SAlexander Kabaev 690f8a1b7d9SAlexander Kabaev // Forward declare the class. 691f8a1b7d9SAlexander Kabaev template<typename _Tp> 692f8a1b7d9SAlexander Kabaev class bitmap_allocator; 693f8a1b7d9SAlexander Kabaev 694f8a1b7d9SAlexander Kabaev // Specialize for void: 695f8a1b7d9SAlexander Kabaev template<> 696f8a1b7d9SAlexander Kabaev class bitmap_allocator<void> 697f8a1b7d9SAlexander Kabaev { 698ffeaf689SAlexander Kabaev public: 699ffeaf689SAlexander Kabaev typedef void* pointer; 700ffeaf689SAlexander Kabaev typedef const void* const_pointer; 701f8a1b7d9SAlexander Kabaev 702f8a1b7d9SAlexander Kabaev // Reference-to-void members are impossible. 703ffeaf689SAlexander Kabaev typedef void value_type; 704f8a1b7d9SAlexander Kabaev template<typename _Tp1> 705f8a1b7d9SAlexander Kabaev struct rebind 706f8a1b7d9SAlexander Kabaev { 707f8a1b7d9SAlexander Kabaev typedef bitmap_allocator<_Tp1> other; 708f8a1b7d9SAlexander Kabaev }; 709ffeaf689SAlexander Kabaev }; 710ffeaf689SAlexander Kabaev 711f8a1b7d9SAlexander Kabaev template<typename _Tp> 712f8a1b7d9SAlexander Kabaev class bitmap_allocator : private free_list 713f8a1b7d9SAlexander Kabaev { 714ffeaf689SAlexander Kabaev public: 715ffeaf689SAlexander Kabaev typedef size_t size_type; 716ffeaf689SAlexander Kabaev typedef ptrdiff_t difference_type; 717ffeaf689SAlexander Kabaev typedef _Tp* pointer; 718ffeaf689SAlexander Kabaev typedef const _Tp* const_pointer; 719ffeaf689SAlexander Kabaev typedef _Tp& reference; 720ffeaf689SAlexander Kabaev typedef const _Tp& const_reference; 721ffeaf689SAlexander Kabaev typedef _Tp value_type; 722f8a1b7d9SAlexander Kabaev typedef free_list::__mutex_type __mutex_type; 723f8a1b7d9SAlexander Kabaev 724f8a1b7d9SAlexander Kabaev template<typename _Tp1> 725f8a1b7d9SAlexander Kabaev struct rebind 726f8a1b7d9SAlexander Kabaev { 727f8a1b7d9SAlexander Kabaev typedef bitmap_allocator<_Tp1> other; 728f8a1b7d9SAlexander Kabaev }; 729ffeaf689SAlexander Kabaev 730ffeaf689SAlexander Kabaev private: 731f8a1b7d9SAlexander Kabaev template<size_t _BSize, size_t _AlignSize> 732f8a1b7d9SAlexander Kabaev struct aligned_size 733ffeaf689SAlexander Kabaev { 734f8a1b7d9SAlexander Kabaev enum 735ffeaf689SAlexander Kabaev { 736f8a1b7d9SAlexander Kabaev modulus = _BSize % _AlignSize, 737f8a1b7d9SAlexander Kabaev value = _BSize + (modulus ? _AlignSize - (modulus) : 0) 738f8a1b7d9SAlexander Kabaev }; 739f8a1b7d9SAlexander Kabaev }; 740ffeaf689SAlexander Kabaev 741f8a1b7d9SAlexander Kabaev struct _Alloc_block 742ffeaf689SAlexander Kabaev { 743f8a1b7d9SAlexander Kabaev char __M_unused[aligned_size<sizeof(value_type), 744f8a1b7d9SAlexander Kabaev _BALLOC_ALIGN_BYTES>::value]; 745f8a1b7d9SAlexander Kabaev }; 746ffeaf689SAlexander Kabaev 747ffeaf689SAlexander Kabaev 748f8a1b7d9SAlexander Kabaev typedef typename std::pair<_Alloc_block*, _Alloc_block*> _Block_pair; 749f8a1b7d9SAlexander Kabaev 750f8a1b7d9SAlexander Kabaev typedef typename 751f8a1b7d9SAlexander Kabaev __detail::__mini_vector<_Block_pair> _BPVector; 752f8a1b7d9SAlexander Kabaev 753f8a1b7d9SAlexander Kabaev #if defined _GLIBCXX_DEBUG 754ffeaf689SAlexander Kabaev // Complexity: O(lg(N)). Where, N is the number of block of size 755ffeaf689SAlexander Kabaev // sizeof(value_type). 756f8a1b7d9SAlexander Kabaev void 757f8a1b7d9SAlexander Kabaev _S_check_for_free_blocks() throw() 758ffeaf689SAlexander Kabaev { 759f8a1b7d9SAlexander Kabaev typedef typename 760f8a1b7d9SAlexander Kabaev __gnu_cxx::__detail::_Ffit_finder<_Alloc_block*> _FFF; 761ffeaf689SAlexander Kabaev _FFF __fff; 762ffeaf689SAlexander Kabaev typedef typename _BPVector::iterator _BPiter; 763f8a1b7d9SAlexander Kabaev _BPiter __bpi = 764f8a1b7d9SAlexander Kabaev __gnu_cxx::__detail::__find_if 765f8a1b7d9SAlexander Kabaev (_S_mem_blocks.begin(), _S_mem_blocks.end(), 766f8a1b7d9SAlexander Kabaev __gnu_cxx::__detail::_Functor_Ref<_FFF>(__fff)); 767f8a1b7d9SAlexander Kabaev 768f8a1b7d9SAlexander Kabaev _GLIBCXX_DEBUG_ASSERT(__bpi == _S_mem_blocks.end()); 769ffeaf689SAlexander Kabaev } 770ffeaf689SAlexander Kabaev #endif 771ffeaf689SAlexander Kabaev 772f8a1b7d9SAlexander Kabaev /** @brief Responsible for exponentially growing the internal 773f8a1b7d9SAlexander Kabaev * memory pool. 774f8a1b7d9SAlexander Kabaev * 775f8a1b7d9SAlexander Kabaev * @throw std::bad_alloc. If memory can not be allocated. 776f8a1b7d9SAlexander Kabaev * 777f8a1b7d9SAlexander Kabaev * @detail Complexity: O(1), but internally depends upon the 778f8a1b7d9SAlexander Kabaev * complexity of the function free_list::_M_get. The part where 779f8a1b7d9SAlexander Kabaev * the bitmap headers are written has complexity: O(X),where X 780f8a1b7d9SAlexander Kabaev * is the number of blocks of size sizeof(value_type) within 781f8a1b7d9SAlexander Kabaev * the newly acquired block. Having a tight bound. 782f8a1b7d9SAlexander Kabaev */ 783f8a1b7d9SAlexander Kabaev void 784f8a1b7d9SAlexander Kabaev _S_refill_pool() throw(std::bad_alloc) 785ffeaf689SAlexander Kabaev { 786f8a1b7d9SAlexander Kabaev #if defined _GLIBCXX_DEBUG 787ffeaf689SAlexander Kabaev _S_check_for_free_blocks(); 788ffeaf689SAlexander Kabaev #endif 789ffeaf689SAlexander Kabaev 790f8a1b7d9SAlexander Kabaev const size_t __num_bitmaps = (_S_block_size 791f8a1b7d9SAlexander Kabaev / size_t(__detail::bits_per_block)); 792f8a1b7d9SAlexander Kabaev const size_t __size_to_allocate = sizeof(size_t) 793f8a1b7d9SAlexander Kabaev + _S_block_size * sizeof(_Alloc_block) 794f8a1b7d9SAlexander Kabaev + __num_bitmaps * sizeof(size_t); 795ffeaf689SAlexander Kabaev 796f8a1b7d9SAlexander Kabaev size_t* __temp = 797f8a1b7d9SAlexander Kabaev reinterpret_cast<size_t*> 798f8a1b7d9SAlexander Kabaev (this->_M_get(__size_to_allocate)); 799ffeaf689SAlexander Kabaev *__temp = 0; 800ffeaf689SAlexander Kabaev ++__temp; 801ffeaf689SAlexander Kabaev 802ffeaf689SAlexander Kabaev // The Header information goes at the Beginning of the Block. 803f8a1b7d9SAlexander Kabaev _Block_pair __bp = 804f8a1b7d9SAlexander Kabaev std::make_pair(reinterpret_cast<_Alloc_block*> 805f8a1b7d9SAlexander Kabaev (__temp + __num_bitmaps), 806f8a1b7d9SAlexander Kabaev reinterpret_cast<_Alloc_block*> 807f8a1b7d9SAlexander Kabaev (__temp + __num_bitmaps) 808ffeaf689SAlexander Kabaev + _S_block_size - 1); 809ffeaf689SAlexander Kabaev 810ffeaf689SAlexander Kabaev // Fill the Vector with this information. 811ffeaf689SAlexander Kabaev _S_mem_blocks.push_back(__bp); 812ffeaf689SAlexander Kabaev 813f8a1b7d9SAlexander Kabaev size_t __bit_mask = 0; // 0 Indicates all Allocated. 814ffeaf689SAlexander Kabaev __bit_mask = ~__bit_mask; // 1 Indicates all Free. 815ffeaf689SAlexander Kabaev 816f8a1b7d9SAlexander Kabaev for (size_t __i = 0; __i < __num_bitmaps; ++__i) 817ffeaf689SAlexander Kabaev __temp[__i] = __bit_mask; 818ffeaf689SAlexander Kabaev 819ffeaf689SAlexander Kabaev _S_block_size *= 2; 820ffeaf689SAlexander Kabaev } 821ffeaf689SAlexander Kabaev 822f8a1b7d9SAlexander Kabaev 823ffeaf689SAlexander Kabaev static _BPVector _S_mem_blocks; 824f8a1b7d9SAlexander Kabaev static size_t _S_block_size; 825f8a1b7d9SAlexander Kabaev static __gnu_cxx::__detail:: 826f8a1b7d9SAlexander Kabaev _Bitmap_counter<_Alloc_block*> _S_last_request; 827ffeaf689SAlexander Kabaev static typename _BPVector::size_type _S_last_dealloc_index; 828ffeaf689SAlexander Kabaev #if defined __GTHREADS 829f8a1b7d9SAlexander Kabaev static __mutex_type _S_mut; 830ffeaf689SAlexander Kabaev #endif 831ffeaf689SAlexander Kabaev 832f8a1b7d9SAlexander Kabaev public: 833f8a1b7d9SAlexander Kabaev 834f8a1b7d9SAlexander Kabaev /** @brief Allocates memory for a single object of size 835f8a1b7d9SAlexander Kabaev * sizeof(_Tp). 836f8a1b7d9SAlexander Kabaev * 837f8a1b7d9SAlexander Kabaev * @throw std::bad_alloc. If memory can not be allocated. 838f8a1b7d9SAlexander Kabaev * 839f8a1b7d9SAlexander Kabaev * @detail Complexity: Worst case complexity is O(N), but that 840f8a1b7d9SAlexander Kabaev * is hardly ever hit. If and when this particular case is 841f8a1b7d9SAlexander Kabaev * encountered, the next few cases are guaranteed to have a 842f8a1b7d9SAlexander Kabaev * worst case complexity of O(1)! That's why this function 843f8a1b7d9SAlexander Kabaev * performs very well on average. You can consider this 844f8a1b7d9SAlexander Kabaev * function to have a complexity referred to commonly as: 845f8a1b7d9SAlexander Kabaev * Amortized Constant time. 846f8a1b7d9SAlexander Kabaev */ 847f8a1b7d9SAlexander Kabaev pointer 848f8a1b7d9SAlexander Kabaev _M_allocate_single_object() throw(std::bad_alloc) 849ffeaf689SAlexander Kabaev { 850ffeaf689SAlexander Kabaev #if defined __GTHREADS 851f8a1b7d9SAlexander Kabaev __gnu_cxx::__scoped_lock __bit_lock(_S_mut); 852ffeaf689SAlexander Kabaev #endif 853ffeaf689SAlexander Kabaev 854f8a1b7d9SAlexander Kabaev // The algorithm is something like this: The last_request 855f8a1b7d9SAlexander Kabaev // variable points to the last accessed Bit Map. When such a 856f8a1b7d9SAlexander Kabaev // condition occurs, we try to find a free block in the 857f8a1b7d9SAlexander Kabaev // current bitmap, or succeeding bitmaps until the last bitmap 858f8a1b7d9SAlexander Kabaev // is reached. If no free block turns up, we resort to First 859f8a1b7d9SAlexander Kabaev // Fit method. 860ffeaf689SAlexander Kabaev 861f8a1b7d9SAlexander Kabaev // WARNING: Do not re-order the condition in the while 862f8a1b7d9SAlexander Kabaev // statement below, because it relies on C++'s short-circuit 863f8a1b7d9SAlexander Kabaev // evaluation. The return from _S_last_request->_M_get() will 864f8a1b7d9SAlexander Kabaev // NOT be dereference able if _S_last_request->_M_finished() 865f8a1b7d9SAlexander Kabaev // returns true. This would inevitably lead to a NULL pointer 866f8a1b7d9SAlexander Kabaev // dereference if tinkered with. 867f8a1b7d9SAlexander Kabaev while (_S_last_request._M_finished() == false 868f8a1b7d9SAlexander Kabaev && (*(_S_last_request._M_get()) == 0)) 869ffeaf689SAlexander Kabaev { 870ffeaf689SAlexander Kabaev _S_last_request.operator++(); 871ffeaf689SAlexander Kabaev } 872ffeaf689SAlexander Kabaev 873ffeaf689SAlexander Kabaev if (__builtin_expect(_S_last_request._M_finished() == true, false)) 874ffeaf689SAlexander Kabaev { 875ffeaf689SAlexander Kabaev // Fall Back to First Fit algorithm. 876f8a1b7d9SAlexander Kabaev typedef typename 877f8a1b7d9SAlexander Kabaev __gnu_cxx::__detail::_Ffit_finder<_Alloc_block*> _FFF; 878ffeaf689SAlexander Kabaev _FFF __fff; 879ffeaf689SAlexander Kabaev typedef typename _BPVector::iterator _BPiter; 880f8a1b7d9SAlexander Kabaev _BPiter __bpi = 881f8a1b7d9SAlexander Kabaev __gnu_cxx::__detail::__find_if 882f8a1b7d9SAlexander Kabaev (_S_mem_blocks.begin(), _S_mem_blocks.end(), 883f8a1b7d9SAlexander Kabaev __gnu_cxx::__detail::_Functor_Ref<_FFF>(__fff)); 884ffeaf689SAlexander Kabaev 885ffeaf689SAlexander Kabaev if (__bpi != _S_mem_blocks.end()) 886ffeaf689SAlexander Kabaev { 887ffeaf689SAlexander Kabaev // Search was successful. Ok, now mark the first bit from 888ffeaf689SAlexander Kabaev // the right as 0, meaning Allocated. This bit is obtained 889ffeaf689SAlexander Kabaev // by calling _M_get() on __fff. 890f8a1b7d9SAlexander Kabaev size_t __nz_bit = _Bit_scan_forward(*__fff._M_get()); 891f8a1b7d9SAlexander Kabaev __detail::__bit_allocate(__fff._M_get(), __nz_bit); 892ffeaf689SAlexander Kabaev 893ffeaf689SAlexander Kabaev _S_last_request._M_reset(__bpi - _S_mem_blocks.begin()); 894ffeaf689SAlexander Kabaev 895ffeaf689SAlexander Kabaev // Now, get the address of the bit we marked as allocated. 896f8a1b7d9SAlexander Kabaev pointer __ret = reinterpret_cast<pointer> 897f8a1b7d9SAlexander Kabaev (__bpi->first + __fff._M_offset() + __nz_bit); 898f8a1b7d9SAlexander Kabaev size_t* __puse_count = 899f8a1b7d9SAlexander Kabaev reinterpret_cast<size_t*> 900f8a1b7d9SAlexander Kabaev (__bpi->first) 901f8a1b7d9SAlexander Kabaev - (__gnu_cxx::__detail::__num_bitmaps(*__bpi) + 1); 902f8a1b7d9SAlexander Kabaev 903ffeaf689SAlexander Kabaev ++(*__puse_count); 904f8a1b7d9SAlexander Kabaev return __ret; 905ffeaf689SAlexander Kabaev } 906ffeaf689SAlexander Kabaev else 907ffeaf689SAlexander Kabaev { 908f8a1b7d9SAlexander Kabaev // Search was unsuccessful. We Add more memory to the 909f8a1b7d9SAlexander Kabaev // pool by calling _S_refill_pool(). 910ffeaf689SAlexander Kabaev _S_refill_pool(); 911ffeaf689SAlexander Kabaev 912f8a1b7d9SAlexander Kabaev // _M_Reset the _S_last_request structure to the first 913f8a1b7d9SAlexander Kabaev // free block's bit map. 914ffeaf689SAlexander Kabaev _S_last_request._M_reset(_S_mem_blocks.size() - 1); 915ffeaf689SAlexander Kabaev 916ffeaf689SAlexander Kabaev // Now, mark that bit as allocated. 917ffeaf689SAlexander Kabaev } 918ffeaf689SAlexander Kabaev } 919ffeaf689SAlexander Kabaev 920f8a1b7d9SAlexander Kabaev // _S_last_request holds a pointer to a valid bit map, that 921f8a1b7d9SAlexander Kabaev // points to a free block in memory. 922f8a1b7d9SAlexander Kabaev size_t __nz_bit = _Bit_scan_forward(*_S_last_request._M_get()); 923f8a1b7d9SAlexander Kabaev __detail::__bit_allocate(_S_last_request._M_get(), __nz_bit); 924ffeaf689SAlexander Kabaev 925f8a1b7d9SAlexander Kabaev pointer __ret = reinterpret_cast<pointer> 926f8a1b7d9SAlexander Kabaev (_S_last_request._M_base() + _S_last_request._M_offset() + __nz_bit); 927f8a1b7d9SAlexander Kabaev 928f8a1b7d9SAlexander Kabaev size_t* __puse_count = reinterpret_cast<size_t*> 929f8a1b7d9SAlexander Kabaev (_S_mem_blocks[_S_last_request._M_where()].first) 930f8a1b7d9SAlexander Kabaev - (__gnu_cxx::__detail:: 931f8a1b7d9SAlexander Kabaev __num_bitmaps(_S_mem_blocks[_S_last_request._M_where()]) + 1); 932f8a1b7d9SAlexander Kabaev 933ffeaf689SAlexander Kabaev ++(*__puse_count); 934f8a1b7d9SAlexander Kabaev return __ret; 935ffeaf689SAlexander Kabaev } 936ffeaf689SAlexander Kabaev 937f8a1b7d9SAlexander Kabaev /** @brief Deallocates memory that belongs to a single object of 938f8a1b7d9SAlexander Kabaev * size sizeof(_Tp). 939f8a1b7d9SAlexander Kabaev * 940f8a1b7d9SAlexander Kabaev * @detail Complexity: O(lg(N)), but the worst case is not hit 941f8a1b7d9SAlexander Kabaev * often! This is because containers usually deallocate memory 942f8a1b7d9SAlexander Kabaev * close to each other and this case is handled in O(1) time by 943f8a1b7d9SAlexander Kabaev * the deallocate function. 944f8a1b7d9SAlexander Kabaev */ 945f8a1b7d9SAlexander Kabaev void 946f8a1b7d9SAlexander Kabaev _M_deallocate_single_object(pointer __p) throw() 947ffeaf689SAlexander Kabaev { 948ffeaf689SAlexander Kabaev #if defined __GTHREADS 949f8a1b7d9SAlexander Kabaev __gnu_cxx::__scoped_lock __bit_lock(_S_mut); 950ffeaf689SAlexander Kabaev #endif 951f8a1b7d9SAlexander Kabaev _Alloc_block* __real_p = reinterpret_cast<_Alloc_block*>(__p); 952ffeaf689SAlexander Kabaev 953ffeaf689SAlexander Kabaev typedef typename _BPVector::iterator _Iterator; 954ffeaf689SAlexander Kabaev typedef typename _BPVector::difference_type _Difference_type; 955ffeaf689SAlexander Kabaev 956ffeaf689SAlexander Kabaev _Difference_type __diff; 957f8a1b7d9SAlexander Kabaev long __displacement; 958ffeaf689SAlexander Kabaev 959f8a1b7d9SAlexander Kabaev _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index >= 0); 960ffeaf689SAlexander Kabaev 961f8a1b7d9SAlexander Kabaev 962f8a1b7d9SAlexander Kabaev if (__gnu_cxx::__detail::_Inclusive_between<_Alloc_block*> 963f8a1b7d9SAlexander Kabaev (__real_p) (_S_mem_blocks[_S_last_dealloc_index])) 964ffeaf689SAlexander Kabaev { 965f8a1b7d9SAlexander Kabaev _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index 966f8a1b7d9SAlexander Kabaev <= _S_mem_blocks.size() - 1); 967ffeaf689SAlexander Kabaev 968ffeaf689SAlexander Kabaev // Initial Assumption was correct! 969ffeaf689SAlexander Kabaev __diff = _S_last_dealloc_index; 970f8a1b7d9SAlexander Kabaev __displacement = __real_p - _S_mem_blocks[__diff].first; 971ffeaf689SAlexander Kabaev } 972ffeaf689SAlexander Kabaev else 973ffeaf689SAlexander Kabaev { 974f8a1b7d9SAlexander Kabaev _Iterator _iter = __gnu_cxx::__detail:: 975f8a1b7d9SAlexander Kabaev __find_if(_S_mem_blocks.begin(), 976f8a1b7d9SAlexander Kabaev _S_mem_blocks.end(), 977f8a1b7d9SAlexander Kabaev __gnu_cxx::__detail:: 978f8a1b7d9SAlexander Kabaev _Inclusive_between<_Alloc_block*>(__real_p)); 979f8a1b7d9SAlexander Kabaev 980f8a1b7d9SAlexander Kabaev _GLIBCXX_DEBUG_ASSERT(_iter != _S_mem_blocks.end()); 981ffeaf689SAlexander Kabaev 982ffeaf689SAlexander Kabaev __diff = _iter - _S_mem_blocks.begin(); 983f8a1b7d9SAlexander Kabaev __displacement = __real_p - _S_mem_blocks[__diff].first; 984ffeaf689SAlexander Kabaev _S_last_dealloc_index = __diff; 985ffeaf689SAlexander Kabaev } 986ffeaf689SAlexander Kabaev 987ffeaf689SAlexander Kabaev // Get the position of the iterator that has been found. 988f8a1b7d9SAlexander Kabaev const size_t __rotate = (__displacement 989f8a1b7d9SAlexander Kabaev % size_t(__detail::bits_per_block)); 990f8a1b7d9SAlexander Kabaev size_t* __bitmapC = 991f8a1b7d9SAlexander Kabaev reinterpret_cast<size_t*> 992f8a1b7d9SAlexander Kabaev (_S_mem_blocks[__diff].first) - 1; 993f8a1b7d9SAlexander Kabaev __bitmapC -= (__displacement / size_t(__detail::bits_per_block)); 994ffeaf689SAlexander Kabaev 995f8a1b7d9SAlexander Kabaev __detail::__bit_free(__bitmapC, __rotate); 996f8a1b7d9SAlexander Kabaev size_t* __puse_count = reinterpret_cast<size_t*> 997f8a1b7d9SAlexander Kabaev (_S_mem_blocks[__diff].first) 998f8a1b7d9SAlexander Kabaev - (__gnu_cxx::__detail::__num_bitmaps(_S_mem_blocks[__diff]) + 1); 999ffeaf689SAlexander Kabaev 1000f8a1b7d9SAlexander Kabaev _GLIBCXX_DEBUG_ASSERT(*__puse_count != 0); 1001ffeaf689SAlexander Kabaev 1002ffeaf689SAlexander Kabaev --(*__puse_count); 1003ffeaf689SAlexander Kabaev 1004ffeaf689SAlexander Kabaev if (__builtin_expect(*__puse_count == 0, false)) 1005ffeaf689SAlexander Kabaev { 1006ffeaf689SAlexander Kabaev _S_block_size /= 2; 1007ffeaf689SAlexander Kabaev 1008f8a1b7d9SAlexander Kabaev // We can safely remove this block. 1009f8a1b7d9SAlexander Kabaev // _Block_pair __bp = _S_mem_blocks[__diff]; 1010f8a1b7d9SAlexander Kabaev this->_M_insert(__puse_count); 1011ffeaf689SAlexander Kabaev _S_mem_blocks.erase(_S_mem_blocks.begin() + __diff); 1012ffeaf689SAlexander Kabaev 1013f8a1b7d9SAlexander Kabaev // Reset the _S_last_request variable to reflect the 1014f8a1b7d9SAlexander Kabaev // erased block. We do this to protect future requests 1015f8a1b7d9SAlexander Kabaev // after the last block has been removed from a particular 1016f8a1b7d9SAlexander Kabaev // memory Chunk, which in turn has been returned to the 1017f8a1b7d9SAlexander Kabaev // free list, and hence had been erased from the vector, 1018f8a1b7d9SAlexander Kabaev // so the size of the vector gets reduced by 1. 1019ffeaf689SAlexander Kabaev if ((_Difference_type)_S_last_request._M_where() >= __diff--) 1020ffeaf689SAlexander Kabaev _S_last_request._M_reset(__diff); 1021ffeaf689SAlexander Kabaev 1022f8a1b7d9SAlexander Kabaev // If the Index into the vector of the region of memory 1023f8a1b7d9SAlexander Kabaev // that might hold the next address that will be passed to 1024ffeaf689SAlexander Kabaev // deallocated may have been invalidated due to the above 1025f8a1b7d9SAlexander Kabaev // erase procedure being called on the vector, hence we 1026f8a1b7d9SAlexander Kabaev // try to restore this invariant too. 1027ffeaf689SAlexander Kabaev if (_S_last_dealloc_index >= _S_mem_blocks.size()) 1028ffeaf689SAlexander Kabaev { 1029ffeaf689SAlexander Kabaev _S_last_dealloc_index =(__diff != -1 ? __diff : 0); 1030f8a1b7d9SAlexander Kabaev _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index >= 0); 1031ffeaf689SAlexander Kabaev } 1032ffeaf689SAlexander Kabaev } 1033ffeaf689SAlexander Kabaev } 1034ffeaf689SAlexander Kabaev 1035ffeaf689SAlexander Kabaev public: 1036ffeaf689SAlexander Kabaev bitmap_allocator() throw() 1037ffeaf689SAlexander Kabaev { } 1038ffeaf689SAlexander Kabaev 1039f8a1b7d9SAlexander Kabaev bitmap_allocator(const bitmap_allocator&) 1040f8a1b7d9SAlexander Kabaev { } 1041ffeaf689SAlexander Kabaev 1042f8a1b7d9SAlexander Kabaev template<typename _Tp1> 1043f8a1b7d9SAlexander Kabaev bitmap_allocator(const bitmap_allocator<_Tp1>&) throw() 1044ffeaf689SAlexander Kabaev { } 1045ffeaf689SAlexander Kabaev 1046ffeaf689SAlexander Kabaev ~bitmap_allocator() throw() 1047ffeaf689SAlexander Kabaev { } 1048ffeaf689SAlexander Kabaev 1049f8a1b7d9SAlexander Kabaev pointer 1050f8a1b7d9SAlexander Kabaev allocate(size_type __n) 1051f8a1b7d9SAlexander Kabaev { 1052f8a1b7d9SAlexander Kabaev if (__builtin_expect(__n > this->max_size(), false)) 1053f8a1b7d9SAlexander Kabaev std::__throw_bad_alloc(); 1054f8a1b7d9SAlexander Kabaev 1055f8a1b7d9SAlexander Kabaev if (__builtin_expect(__n == 1, true)) 1056f8a1b7d9SAlexander Kabaev return this->_M_allocate_single_object(); 1057f8a1b7d9SAlexander Kabaev else 1058f8a1b7d9SAlexander Kabaev { 1059f8a1b7d9SAlexander Kabaev const size_type __b = __n * sizeof(value_type); 1060f8a1b7d9SAlexander Kabaev return reinterpret_cast<pointer>(::operator new(__b)); 1061f8a1b7d9SAlexander Kabaev } 1062f8a1b7d9SAlexander Kabaev } 1063f8a1b7d9SAlexander Kabaev 1064f8a1b7d9SAlexander Kabaev pointer 1065f8a1b7d9SAlexander Kabaev allocate(size_type __n, typename bitmap_allocator<void>::const_pointer) 1066f8a1b7d9SAlexander Kabaev { return allocate(__n); } 1067f8a1b7d9SAlexander Kabaev 1068f8a1b7d9SAlexander Kabaev void 1069f8a1b7d9SAlexander Kabaev deallocate(pointer __p, size_type __n) throw() 1070f8a1b7d9SAlexander Kabaev { 1071f8a1b7d9SAlexander Kabaev if (__builtin_expect(__p != 0, true)) 1072ffeaf689SAlexander Kabaev { 1073ffeaf689SAlexander Kabaev if (__builtin_expect(__n == 1, true)) 1074f8a1b7d9SAlexander Kabaev this->_M_deallocate_single_object(__p); 1075ffeaf689SAlexander Kabaev else 1076f8a1b7d9SAlexander Kabaev ::operator delete(__p); 1077f8a1b7d9SAlexander Kabaev } 1078ffeaf689SAlexander Kabaev } 1079ffeaf689SAlexander Kabaev 1080f8a1b7d9SAlexander Kabaev pointer 1081f8a1b7d9SAlexander Kabaev address(reference __r) const 1082f8a1b7d9SAlexander Kabaev { return &__r; } 1083ffeaf689SAlexander Kabaev 1084f8a1b7d9SAlexander Kabaev const_pointer 1085f8a1b7d9SAlexander Kabaev address(const_reference __r) const 1086f8a1b7d9SAlexander Kabaev { return &__r; } 1087ffeaf689SAlexander Kabaev 1088f8a1b7d9SAlexander Kabaev size_type 1089f8a1b7d9SAlexander Kabaev max_size() const throw() 1090f8a1b7d9SAlexander Kabaev { return size_type(-1) / sizeof(value_type); } 1091ffeaf689SAlexander Kabaev 1092f8a1b7d9SAlexander Kabaev void 1093f8a1b7d9SAlexander Kabaev construct(pointer __p, const_reference __data) 1094f8a1b7d9SAlexander Kabaev { ::new(__p) value_type(__data); } 1095ffeaf689SAlexander Kabaev 1096f8a1b7d9SAlexander Kabaev void 1097f8a1b7d9SAlexander Kabaev destroy(pointer __p) 1098f8a1b7d9SAlexander Kabaev { __p->~value_type(); } 1099ffeaf689SAlexander Kabaev }; 1100ffeaf689SAlexander Kabaev 1101f8a1b7d9SAlexander Kabaev template<typename _Tp1, typename _Tp2> 1102f8a1b7d9SAlexander Kabaev bool 1103f8a1b7d9SAlexander Kabaev operator==(const bitmap_allocator<_Tp1>&, 1104f8a1b7d9SAlexander Kabaev const bitmap_allocator<_Tp2>&) throw() 1105f8a1b7d9SAlexander Kabaev { return true; } 1106f8a1b7d9SAlexander Kabaev 1107f8a1b7d9SAlexander Kabaev template<typename _Tp1, typename _Tp2> 1108f8a1b7d9SAlexander Kabaev bool 1109f8a1b7d9SAlexander Kabaev operator!=(const bitmap_allocator<_Tp1>&, 1110f8a1b7d9SAlexander Kabaev const bitmap_allocator<_Tp2>&) throw() 1111f8a1b7d9SAlexander Kabaev { return false; } 1112f8a1b7d9SAlexander Kabaev 1113f8a1b7d9SAlexander Kabaev // Static member definitions. 1114ffeaf689SAlexander Kabaev template<typename _Tp> 1115f8a1b7d9SAlexander Kabaev typename bitmap_allocator<_Tp>::_BPVector 1116f8a1b7d9SAlexander Kabaev bitmap_allocator<_Tp>::_S_mem_blocks; 1117ffeaf689SAlexander Kabaev 1118ffeaf689SAlexander Kabaev template<typename _Tp> 1119f8a1b7d9SAlexander Kabaev size_t bitmap_allocator<_Tp>::_S_block_size = 1120f8a1b7d9SAlexander Kabaev 2 * size_t(__detail::bits_per_block); 1121ffeaf689SAlexander Kabaev 1122ffeaf689SAlexander Kabaev template<typename _Tp> 1123ffeaf689SAlexander Kabaev typename __gnu_cxx::bitmap_allocator<_Tp>::_BPVector::size_type 1124ffeaf689SAlexander Kabaev bitmap_allocator<_Tp>::_S_last_dealloc_index = 0; 1125ffeaf689SAlexander Kabaev 1126ffeaf689SAlexander Kabaev template<typename _Tp> 1127f8a1b7d9SAlexander Kabaev __gnu_cxx::__detail::_Bitmap_counter 1128f8a1b7d9SAlexander Kabaev <typename bitmap_allocator<_Tp>::_Alloc_block*> 1129ffeaf689SAlexander Kabaev bitmap_allocator<_Tp>::_S_last_request(_S_mem_blocks); 1130ffeaf689SAlexander Kabaev 1131ffeaf689SAlexander Kabaev #if defined __GTHREADS 1132ffeaf689SAlexander Kabaev template<typename _Tp> 1133f8a1b7d9SAlexander Kabaev typename bitmap_allocator<_Tp>::__mutex_type 1134ffeaf689SAlexander Kabaev bitmap_allocator<_Tp>::_S_mut; 1135ffeaf689SAlexander Kabaev #endif 1136ffeaf689SAlexander Kabaev 1137f8a1b7d9SAlexander Kabaev _GLIBCXX_END_NAMESPACE 1138ffeaf689SAlexander Kabaev 1139f8a1b7d9SAlexander Kabaev #endif 1140ffeaf689SAlexander Kabaev 1141