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