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