// Bitmap Allocator. -*- C++ -*-
-// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+// Copyright (C) 2004-2024 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 2, or (at your option)
+// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING. If not, write to the Free
-// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-// USA.
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
-// As a special exception, you may use this file as part of a free software
-// library without restriction. Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License. This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
/** @file ext/bitmap_allocator.h
* This file is a GNU extension to the Standard C++ Library.
#ifndef _BITMAP_ALLOCATOR_H
#define _BITMAP_ALLOCATOR_H 1
-// For std::size_t, and ptrdiff_t.
-#include <cstddef>
+#include <bits/requires_hosted.h> // GNU extensions are currently omitted
-// For __throw_bad_alloc().
-#include <bits/functexcept.h>
-
-// For std::pair.
-#include <utility>
-
-// For greater_equal, and less_equal.
-#include <functional>
-
-// For operator new.
-#include <new>
-
-// For __gthread_mutex_t, __gthread_mutex_lock and __gthread_mutex_unlock.
-#include <bits/gthr.h>
-
-// Define this to enable error checking withing the allocator
-// itself(to debug the allocator itself).
-//#define _BALLOC_SANITY_CHECK
+#include <utility> // For std::pair.
+#include <bits/functexcept.h> // For __throw_bad_alloc().
+#include <bits/stl_function.h> // For greater_equal, and less_equal.
+#include <new> // For operator new.
+#include <debug/debug.h> // _GLIBCXX_DEBUG_ASSERT
+#include <ext/concurrence.h>
+#include <bits/move.h>
/** @brief The constant in the expression below is the alignment
* required in bytes.
*/
#define _BALLOC_ALIGN_BYTES 8
-#if defined _BALLOC_SANITY_CHECK
-#include <cassert>
-#define _BALLOC_ASSERT(_EXPR) assert(_EXPR)
-#else
-#define _BALLOC_ASSERT(_EXPR)
-#endif
-
-
-_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
-
- using std::size_t;
- using std::ptrdiff_t;
-
-#if defined __GTHREADS
- namespace
- {
- /** @brief If true, then the application being compiled will be
- * using threads, so use mutexes as a synchronization primitive,
- * else do no use any synchronization primitives.
- */
- bool const __threads_enabled = __gthread_active_p();
- } // anonymous namespace
-#endif
-
-#if defined __GTHREADS
- /** @class _Mutex bitmap_allocator.h bitmap_allocator.h
- *
- * @brief _Mutex is an OO-Wrapper for __gthread_mutex_t.
- *
- * It does not allow you to copy or assign an already initialized
- * mutex. This is used merely as a convenience for the locking
- * classes.
- */
- class _Mutex
- {
- __gthread_mutex_t _M_mut;
-
- // Prevent Copying and assignment.
- _Mutex(_Mutex const&);
- _Mutex& operator=(_Mutex const&);
-
- public:
- _Mutex()
- {
- if (__threads_enabled)
- {
-#if !defined __GTHREAD_MUTEX_INIT
- __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mut);
-#else
- __gthread_mutex_t __mtemp = __GTHREAD_MUTEX_INIT;
- _M_mut = __mtemp;
-#endif
- }
- }
-
- ~_Mutex()
- {
- // Gthreads does not define a Mutex Destruction Function.
- }
-
- __gthread_mutex_t*
- _M_get() { return &_M_mut; }
- };
-
- /** @class _Lock bitmap_allocator.h bitmap_allocator.h
- *
- * @brief _Lock is a simple manual locking class which allows you to
- * manually lock and unlock a mutex associated with the lock.
- *
- * There is no automatic locking or unlocking happening without the
- * programmer's explicit instructions. This class unlocks the mutex
- * ONLY if it has not been locked. However, this check does not
- * apply for locking, and wayward use may cause dead-locks.
- */
- class _Lock
- {
- _Mutex* _M_pmt;
- bool _M_locked;
-
- // Prevent Copying and assignment.
- _Lock(_Lock const&);
- _Lock& operator=(_Lock const&);
-
- public:
- _Lock(_Mutex* __mptr)
- : _M_pmt(__mptr), _M_locked(false)
- { }
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
- void
- _M_lock()
- {
- if (__threads_enabled)
- {
- _M_locked = true;
- __gthread_mutex_lock(_M_pmt->_M_get());
- }
- }
-
- void
- _M_unlock()
- {
- if (__threads_enabled)
- {
- if (__builtin_expect(_M_locked, true))
- {
- __gthread_mutex_unlock(_M_pmt->_M_get());
- _M_locked = false;
- }
- }
- }
-
- ~_Lock() { }
- };
-
- /** @class _Auto_Lock bitmap_allocator.h bitmap_allocator.h
- *
- * @brief _Auto_Lock locks the associated mutex on construction, and
- * unlocks on destruction.
- *
- * There are no checks performed, and this class follows the RAII
- * principle.
- */
- class _Auto_Lock
- {
- _Mutex* _M_pmt;
- // Prevent Copying and assignment.
- _Auto_Lock(_Auto_Lock const&);
- _Auto_Lock& operator=(_Auto_Lock const&);
-
- void
- _M_lock()
- {
- if (__threads_enabled)
- __gthread_mutex_lock(_M_pmt->_M_get());
- }
-
- void
- _M_unlock()
- {
- if (__threads_enabled)
- __gthread_mutex_unlock(_M_pmt->_M_get());
- }
-
- public:
- _Auto_Lock(_Mutex* __mptr) : _M_pmt(__mptr)
- { this->_M_lock(); }
-
- ~_Auto_Lock() { this->_M_unlock(); }
- };
-#endif
-
- namespace balloc
+ namespace __detail
{
/** @class __mini_vector bitmap_allocator.h bitmap_allocator.h
*
* It is to be used only for built-in types or PODs. Notable
* differences are:
*
- * @detail
* 1. Not all accessor functions are present.
* 2. Used ONLY for PODs.
* 3. No Allocator template argument. Uses ::operator new() to get
typedef _Tp* pointer;
typedef _Tp& reference;
typedef const _Tp& const_reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
typedef pointer iterator;
private:
_M_space_left() const throw()
{ return _M_end_of_storage - _M_finish; }
- pointer
+ _GLIBCXX_NODISCARD pointer
allocate(size_type __n)
{ return static_cast<pointer>(::operator new(__n * sizeof(_Tp))); }
// insert(iterator, const_reference), erase(iterator),
// begin(), end(), back(), operator[].
- __mini_vector() : _M_start(0), _M_finish(0),
- _M_end_of_storage(0)
- { }
-
-#if 0
- ~__mini_vector()
- {
- if (this->_M_start)
- {
- this->deallocate(this->_M_start, this->_M_end_of_storage
- - this->_M_start);
- }
- }
-#endif
+ __mini_vector()
+ : _M_start(0), _M_finish(0), _M_end_of_storage(0) { }
size_type
size() const throw()
struct __mv_iter_traits<_Tp*>
{
typedef _Tp value_type;
- typedef ptrdiff_t difference_type;
+ typedef std::ptrdiff_t difference_type;
};
enum
{
bits_per_byte = 8,
- bits_per_block = sizeof(size_t) * size_t(bits_per_byte)
+ bits_per_block = sizeof(std::size_t) * std::size_t(bits_per_byte)
};
template<typename _ForwardIterator, typename _Tp, typename _Compare>
__lower_bound(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val, _Compare __comp)
{
- typedef typename __mv_iter_traits<_ForwardIterator>::value_type
- _ValueType;
typedef typename __mv_iter_traits<_ForwardIterator>::difference_type
_DistanceType;
return __first;
}
- template<typename _InputIterator, typename _Predicate>
- inline _InputIterator
- __find_if(_InputIterator __first, _InputIterator __last, _Predicate __p)
- {
- while (__first != __last && !__p(*__first))
- ++__first;
- return __first;
- }
-
/** @brief The number of Blocks pointed to by the address pair
* passed to the function.
*/
template<typename _AddrPair>
- inline size_t
+ inline std::size_t
__num_blocks(_AddrPair __ap)
{ return (__ap.second - __ap.first) + 1; }
* passed to the function.
*/
template<typename _AddrPair>
- inline size_t
+ inline std::size_t
__num_bitmaps(_AddrPair __ap)
- { return __num_blocks(__ap) / size_t(bits_per_block); }
+ { return __num_blocks(__ap) / std::size_t(bits_per_block); }
// _Tp should be a pointer type.
template<typename _Tp>
class _Inclusive_between
- : public std::unary_function<typename std::pair<_Tp, _Tp>, bool>
{
typedef _Tp pointer;
pointer _M_ptr_value;
// Used to pass a Functor to functions by reference.
template<typename _Functor>
class _Functor_Ref
- : public std::unary_function<typename _Functor::argument_type,
- typename _Functor::result_type>
{
_Functor& _M_fref;
// the vector.
template<typename _Tp>
class _Ffit_finder
- : public std::unary_function<typename std::pair<_Tp, _Tp>, bool>
{
- typedef typename std::pair<_Tp, _Tp> _Block_pair;
- typedef typename balloc::__mini_vector<_Block_pair> _BPVector;
+ typedef std::pair<_Tp, _Tp> _Block_pair;
+ typedef __detail::__mini_vector<_Block_pair> _BPVector;
typedef typename _BPVector::difference_type _Counter_type;
- size_t* _M_pbitmap;
+ std::size_t* _M_pbitmap;
_Counter_type _M_data_offset;
public:
+ typedef bool result_type;
+ typedef _Block_pair argument_type;
+
_Ffit_finder() : _M_pbitmap(0), _M_data_offset(0)
{ }
bool
operator()(_Block_pair __bp) throw()
{
+ using std::size_t;
// Set the _rover to the last physical location bitmap,
// which is the bitmap which belongs to the first free
// block. Thus, the bitmaps are in exact reverse order of
- // the actual memory layout. So, we count down the bimaps,
+ // the actual memory layout. So, we count down the bitmaps,
// which is the same as moving up the memory.
// If the used count stored at the start of the Bit Map headers
// is equal to the number of Objects that the current Block can
// store, then there is definitely no space for another single
// object, so just return false.
- _Counter_type __diff =
- __gnu_cxx::balloc::__num_bitmaps(__bp);
+ _Counter_type __diff = __detail::__num_bitmaps(__bp);
if (*(reinterpret_cast<size_t*>
- (__bp.first) - (__diff + 1))
- == __gnu_cxx::balloc::__num_blocks(__bp))
+ (__bp.first) - (__diff + 1)) == __detail::__num_blocks(__bp))
return false;
size_t* __rover = reinterpret_cast<size_t*>(__bp.first) - 1;
}
return false;
}
-
- size_t*
+ std::size_t*
_M_get() const throw()
{ return _M_pbitmap; }
_Counter_type
_M_offset() const throw()
- { return _M_data_offset * size_t(bits_per_block); }
+ { return _M_data_offset * std::size_t(bits_per_block); }
};
-
/** @class _Bitmap_counter bitmap_allocator.h bitmap_allocator.h
*
* @brief The bitmap counter which acts as the bitmap
template<typename _Tp>
class _Bitmap_counter
{
- typedef typename balloc::__mini_vector<typename std::pair<_Tp, _Tp> >
- _BPVector;
+ typedef typename
+ __detail::__mini_vector<typename std::pair<_Tp, _Tp> > _BPVector;
typedef typename _BPVector::size_type _Index_type;
typedef _Tp pointer;
-
+
_BPVector& _M_vbp;
- size_t* _M_curr_bmap;
- size_t* _M_last_bmap_in_block;
+ std::size_t* _M_curr_bmap;
+ std::size_t* _M_last_bmap_in_block;
_Index_type _M_curr_index;
public:
}
_M_curr_index = __index;
- _M_curr_bmap = reinterpret_cast<size_t*>
+ _M_curr_bmap = reinterpret_cast<std::size_t*>
(_M_vbp[_M_curr_index].first) - 1;
- _BALLOC_ASSERT(__index <= (long)_M_vbp.size() - 1);
+ _GLIBCXX_DEBUG_ASSERT(__index <= (long)_M_vbp.size() - 1);
_M_last_bmap_in_block = _M_curr_bmap
- ((_M_vbp[_M_curr_index].second
- _M_vbp[_M_curr_index].first + 1)
- / size_t(bits_per_block) - 1);
+ / std::size_t(bits_per_block) - 1);
}
// Dangerous Function! Use with extreme care. Pass to this
// function ONLY those values that are known to be correct,
// otherwise this will mess up big time.
void
- _M_set_internal_bitmap(size_t* __new_internal_marker) throw()
+ _M_set_internal_bitmap(std::size_t* __new_internal_marker) throw()
{ _M_curr_bmap = __new_internal_marker; }
bool
return *this;
}
- size_t*
+ std::size_t*
_M_get() const throw()
{ return _M_curr_bmap; }
_Index_type
_M_offset() const throw()
{
- return size_t(bits_per_block)
- * ((reinterpret_cast<size_t*>(this->_M_base())
+ return std::size_t(bits_per_block)
+ * ((reinterpret_cast<std::size_t*>(this->_M_base())
- _M_curr_bmap) - 1);
}
* corresponding bit in the bit-map.
*/
inline void
- __bit_allocate(size_t* __pbmap, size_t __pos) throw()
+ __bit_allocate(std::size_t* __pbmap, std::size_t __pos) throw()
{
- size_t __mask = 1 << __pos;
+ std::size_t __mask = 1 << __pos;
__mask = ~__mask;
*__pbmap &= __mask;
}
* corresponding bit in the bit-map.
*/
inline void
- __bit_free(size_t* __pbmap, size_t __pos) throw()
+ __bit_free(std::size_t* __pbmap, std::size_t __pos) throw()
{
- size_t __mask = 1 << __pos;
+ std::size_t __mask = 1 << __pos;
*__pbmap |= __mask;
}
- } // namespace balloc
+ } // namespace __detail
/** @brief Generic Version of the bsf instruction.
*/
- inline size_t
- _Bit_scan_forward(size_t __num)
- { return static_cast<size_t>(__builtin_ctzl(__num)); }
+ inline std::size_t
+ _Bit_scan_forward(std::size_t __num)
+ { return static_cast<std::size_t>(__builtin_ctzl(__num)); }
/** @class free_list bitmap_allocator.h bitmap_allocator.h
*
*/
class free_list
{
- typedef size_t* value_type;
- typedef balloc::__mini_vector<value_type> vector_type;
- typedef vector_type::iterator iterator;
+ public:
+ typedef std::size_t* value_type;
+ typedef __detail::__mini_vector<value_type> vector_type;
+ typedef vector_type::iterator iterator;
+ typedef __mutex __mutex_type;
+ private:
struct _LT_pointer_compare
{
bool
- operator()(const size_t* __pui,
- const size_t __cui) const throw()
+ operator()(const std::size_t* __pui,
+ const std::size_t __cui) const throw()
{ return *__pui < __cui; }
};
#if defined __GTHREADS
- _Mutex*
+ __mutex_type&
_M_get_mutex()
{
- static _Mutex _S_mutex;
- return &_S_mutex;
+ static __mutex_type _S_mutex;
+ return _S_mutex;
}
#endif
* @param __addr The pointer to the memory block to be
* validated.
*
- * @detail Validates the memory block passed to this function and
+ * Validates the memory block passed to this function and
* appropriately performs the action of managing the free list of
* blocks by adding this block to the free list or deleting this
* or larger blocks from the free list.
*/
void
- _M_validate(size_t* __addr) throw()
+ _M_validate(std::size_t* __addr) throw()
{
vector_type& __free_list = _M_get_free_list();
const vector_type::size_type __max_size = 64;
else
{
// Deallocate the last block in the list of free lists,
- // and insert the new one in it's correct position.
+ // and insert the new one in its correct position.
::operator delete(static_cast<void*>(__free_list.back()));
__free_list.pop_back();
}
}
// Just add the block to the list of free lists unconditionally.
- iterator __temp = __gnu_cxx::balloc::__lower_bound
+ iterator __temp = __detail::__lower_bound
(__free_list.begin(), __free_list.end(),
*__addr, _LT_pointer_compare());
* false.
*/
bool
- _M_should_i_give(size_t __block_size,
- size_t __required_size) throw()
+ _M_should_i_give(std::size_t __block_size,
+ std::size_t __required_size) throw()
{
- const size_t __max_wastage_percentage = 36;
+ const std::size_t __max_wastage_percentage = 36;
if (__block_size >= __required_size &&
(((__block_size - __required_size) * 100 / __block_size)
< __max_wastage_percentage))
* by a call to the _M_get function.
*/
inline void
- _M_insert(size_t* __addr) throw()
+ _M_insert(std::size_t* __addr) throw()
{
#if defined __GTHREADS
- _Auto_Lock __bfl_lock(_M_get_mutex());
+ __scoped_lock __bfl_lock(_M_get_mutex());
#endif
// Call _M_validate to decide what should be done with
// this particular free list.
- this->_M_validate(reinterpret_cast<size_t*>(__addr) - 1);
+ this->_M_validate(reinterpret_cast<std::size_t*>(__addr) - 1);
// See discussion as to why this is 1!
}
* @return A pointer to the new memory block of size at least
* equal to that requested.
*/
- size_t*
- _M_get(size_t __sz) throw(std::bad_alloc);
+ std::size_t*
+ _M_get(std::size_t __sz) _GLIBCXX_THROW(std::bad_alloc);
/** @brief This function just clears the internal Free List, and
* gives back all the memory to the OS.
};
};
+ /**
+ * @brief Bitmap Allocator, primary template.
+ * @ingroup allocators
+ */
template<typename _Tp>
class bitmap_allocator : private free_list
{
public:
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef _Tp* pointer;
- typedef const _Tp* const_pointer;
- typedef _Tp& reference;
- typedef const _Tp& const_reference;
- typedef _Tp value_type;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef _Tp* pointer;
+ typedef const _Tp* const_pointer;
+ typedef _Tp& reference;
+ typedef const _Tp& const_reference;
+ typedef _Tp value_type;
+ typedef free_list::__mutex_type __mutex_type;
+
template<typename _Tp1>
struct rebind
{
typedef bitmap_allocator<_Tp1> other;
};
+#if __cplusplus >= 201103L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2103. propagate_on_container_move_assignment
+ typedef std::true_type propagate_on_container_move_assignment;
+#endif
+
private:
- template<size_t _BSize, size_t _AlignSize>
+ template<std::size_t _BSize, std::size_t _AlignSize>
struct aligned_size
{
enum
typedef typename std::pair<_Alloc_block*, _Alloc_block*> _Block_pair;
- typedef typename
- balloc::__mini_vector<_Block_pair> _BPVector;
+ typedef typename __detail::__mini_vector<_Block_pair> _BPVector;
+ typedef typename _BPVector::iterator _BPiter;
+
+ template<typename _Predicate>
+ static _BPiter
+ _S_find(_Predicate __p)
+ {
+ _BPiter __first = _S_mem_blocks.begin();
+ while (__first != _S_mem_blocks.end() && !__p(*__first))
+ ++__first;
+ return __first;
+ }
-#if defined _BALLOC_SANITY_CHECK
+#if defined _GLIBCXX_DEBUG
// Complexity: O(lg(N)). Where, N is the number of block of size
// sizeof(value_type).
void
_S_check_for_free_blocks() throw()
{
- typedef typename
- __gnu_cxx::balloc::_Ffit_finder<_Alloc_block*> _FFF;
- _FFF __fff;
- typedef typename _BPVector::iterator _BPiter;
- _BPiter __bpi =
- __gnu_cxx::balloc::__find_if
- (_S_mem_blocks.begin(), _S_mem_blocks.end(),
- __gnu_cxx::balloc::_Functor_Ref<_FFF>(__fff));
-
- _BALLOC_ASSERT(__bpi == _S_mem_blocks.end());
+ typedef typename __detail::_Ffit_finder<_Alloc_block*> _FFF;
+ _BPiter __bpi = _S_find(_FFF());
+
+ _GLIBCXX_DEBUG_ASSERT(__bpi == _S_mem_blocks.end());
}
#endif
/** @brief Responsible for exponentially growing the internal
* memory pool.
*
- * @throw std::bad_alloc. If memory can not be allocated.
+ * @throw std::bad_alloc. If memory cannot be allocated.
*
- * @detail Complexity: O(1), but internally depends upon the
+ * Complexity: O(1), but internally depends upon the
* complexity of the function free_list::_M_get. The part where
* the bitmap headers are written has complexity: O(X),where X
* is the number of blocks of size sizeof(value_type) within
* the newly acquired block. Having a tight bound.
*/
void
- _S_refill_pool() throw(std::bad_alloc)
+ _S_refill_pool() _GLIBCXX_THROW(std::bad_alloc)
{
-#if defined _BALLOC_SANITY_CHECK
+ using std::size_t;
+#if defined _GLIBCXX_DEBUG
_S_check_for_free_blocks();
#endif
const size_t __num_bitmaps = (_S_block_size
- / size_t(balloc::bits_per_block));
+ / size_t(__detail::bits_per_block));
const size_t __size_to_allocate = sizeof(size_t)
+ _S_block_size * sizeof(_Alloc_block)
+ __num_bitmaps * sizeof(size_t);
- size_t* __temp =
- reinterpret_cast<size_t*>
- (this->_M_get(__size_to_allocate));
+ size_t* __temp =
+ reinterpret_cast<size_t*>(this->_M_get(__size_to_allocate));
*__temp = 0;
++__temp;
// Fill the Vector with this information.
_S_mem_blocks.push_back(__bp);
- size_t __bit_mask = 0; // 0 Indicates all Allocated.
- __bit_mask = ~__bit_mask; // 1 Indicates all Free.
-
for (size_t __i = 0; __i < __num_bitmaps; ++__i)
- __temp[__i] = __bit_mask;
+ __temp[__i] = ~static_cast<size_t>(0); // 1 Indicates all Free.
_S_block_size *= 2;
}
-
static _BPVector _S_mem_blocks;
- static size_t _S_block_size;
- static __gnu_cxx::balloc::
- _Bitmap_counter<_Alloc_block*> _S_last_request;
+ static std::size_t _S_block_size;
+ static __detail::_Bitmap_counter<_Alloc_block*> _S_last_request;
static typename _BPVector::size_type _S_last_dealloc_index;
#if defined __GTHREADS
- static _Mutex _S_mut;
+ static __mutex_type _S_mut;
#endif
public:
/** @brief Allocates memory for a single object of size
* sizeof(_Tp).
*
- * @throw std::bad_alloc. If memory can not be allocated.
+ * @throw std::bad_alloc. If memory cannot be allocated.
*
- * @detail Complexity: Worst case complexity is O(N), but that
+ * Complexity: Worst case complexity is O(N), but that
* is hardly ever hit. If and when this particular case is
* encountered, the next few cases are guaranteed to have a
* worst case complexity of O(1)! That's why this function
* Amortized Constant time.
*/
pointer
- _M_allocate_single_object() throw(std::bad_alloc)
+ _M_allocate_single_object() _GLIBCXX_THROW(std::bad_alloc)
{
+ using std::size_t;
#if defined __GTHREADS
- _Auto_Lock __bit_lock(&_S_mut);
+ __scoped_lock __bit_lock(_S_mut);
#endif
// The algorithm is something like this: The last_request
// dereference if tinkered with.
while (_S_last_request._M_finished() == false
&& (*(_S_last_request._M_get()) == 0))
- {
- _S_last_request.operator++();
- }
+ _S_last_request.operator++();
if (__builtin_expect(_S_last_request._M_finished() == true, false))
{
// Fall Back to First Fit algorithm.
- typedef typename
- __gnu_cxx::balloc::_Ffit_finder<_Alloc_block*> _FFF;
+ typedef typename __detail::_Ffit_finder<_Alloc_block*> _FFF;
_FFF __fff;
- typedef typename _BPVector::iterator _BPiter;
- _BPiter __bpi =
- __gnu_cxx::balloc::__find_if
- (_S_mem_blocks.begin(), _S_mem_blocks.end(),
- __gnu_cxx::balloc::_Functor_Ref<_FFF>(__fff));
+ _BPiter __bpi = _S_find(__detail::_Functor_Ref<_FFF>(__fff));
if (__bpi != _S_mem_blocks.end())
{
// the right as 0, meaning Allocated. This bit is obtained
// by calling _M_get() on __fff.
size_t __nz_bit = _Bit_scan_forward(*__fff._M_get());
- balloc::__bit_allocate(__fff._M_get(), __nz_bit);
+ __detail::__bit_allocate(__fff._M_get(), __nz_bit);
_S_last_request._M_reset(__bpi - _S_mem_blocks.begin());
(__bpi->first + __fff._M_offset() + __nz_bit);
size_t* __puse_count =
reinterpret_cast<size_t*>
- (__bpi->first)
- - (__gnu_cxx::balloc::__num_bitmaps(*__bpi) + 1);
+ (__bpi->first) - (__detail::__num_bitmaps(*__bpi) + 1);
++(*__puse_count);
return __ret;
// _S_last_request holds a pointer to a valid bit map, that
// points to a free block in memory.
size_t __nz_bit = _Bit_scan_forward(*_S_last_request._M_get());
- balloc::__bit_allocate(_S_last_request._M_get(), __nz_bit);
+ __detail::__bit_allocate(_S_last_request._M_get(), __nz_bit);
pointer __ret = reinterpret_cast<pointer>
(_S_last_request._M_base() + _S_last_request._M_offset() + __nz_bit);
size_t* __puse_count = reinterpret_cast<size_t*>
(_S_mem_blocks[_S_last_request._M_where()].first)
- - (__gnu_cxx::balloc::
+ - (__detail::
__num_bitmaps(_S_mem_blocks[_S_last_request._M_where()]) + 1);
++(*__puse_count);
/** @brief Deallocates memory that belongs to a single object of
* size sizeof(_Tp).
*
- * @detail Complexity: O(lg(N)), but the worst case is not hit
+ * Complexity: O(lg(N)), but the worst case is not hit
* often! This is because containers usually deallocate memory
* close to each other and this case is handled in O(1) time by
* the deallocate function.
void
_M_deallocate_single_object(pointer __p) throw()
{
+ using std::size_t;
#if defined __GTHREADS
- _Auto_Lock __bit_lock(&_S_mut);
+ __scoped_lock __bit_lock(_S_mut);
#endif
_Alloc_block* __real_p = reinterpret_cast<_Alloc_block*>(__p);
_Difference_type __diff;
long __displacement;
- _BALLOC_ASSERT(_S_last_dealloc_index >= 0);
+ _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index >= 0);
-
- if (__gnu_cxx::balloc::_Inclusive_between<_Alloc_block*>
- (__real_p)
- (_S_mem_blocks[_S_last_dealloc_index]))
+ __detail::_Inclusive_between<_Alloc_block*> __ibt(__real_p);
+ if (__ibt(_S_mem_blocks[_S_last_dealloc_index]))
{
- _BALLOC_ASSERT(_S_last_dealloc_index <= _S_mem_blocks.size() - 1);
+ _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index
+ <= _S_mem_blocks.size() - 1);
// Initial Assumption was correct!
__diff = _S_last_dealloc_index;
}
else
{
- _Iterator _iter =
- __gnu_cxx::balloc::
- __find_if(_S_mem_blocks.begin(),
- _S_mem_blocks.end(),
- __gnu_cxx::balloc::
- _Inclusive_between<_Alloc_block*>(__real_p));
+ _Iterator _iter = _S_find(__ibt);
- _BALLOC_ASSERT(_iter != _S_mem_blocks.end());
+ _GLIBCXX_DEBUG_ASSERT(_iter != _S_mem_blocks.end());
__diff = _iter - _S_mem_blocks.begin();
__displacement = __real_p - _S_mem_blocks[__diff].first;
// Get the position of the iterator that has been found.
const size_t __rotate = (__displacement
- % size_t(balloc::bits_per_block));
+ % size_t(__detail::bits_per_block));
size_t* __bitmapC =
reinterpret_cast<size_t*>
(_S_mem_blocks[__diff].first) - 1;
- __bitmapC -= (__displacement / size_t(balloc::bits_per_block));
+ __bitmapC -= (__displacement / size_t(__detail::bits_per_block));
- balloc::__bit_free(__bitmapC, __rotate);
+ __detail::__bit_free(__bitmapC, __rotate);
size_t* __puse_count = reinterpret_cast<size_t*>
(_S_mem_blocks[__diff].first)
- - (__gnu_cxx::balloc::__num_bitmaps(_S_mem_blocks[__diff]) + 1);
+ - (__detail::__num_bitmaps(_S_mem_blocks[__diff]) + 1);
- _BALLOC_ASSERT(*__puse_count != 0);
+ _GLIBCXX_DEBUG_ASSERT(*__puse_count != 0);
--(*__puse_count);
if (_S_last_dealloc_index >= _S_mem_blocks.size())
{
_S_last_dealloc_index =(__diff != -1 ? __diff : 0);
- _BALLOC_ASSERT(_S_last_dealloc_index >= 0);
+ _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index >= 0);
}
}
}
public:
- bitmap_allocator() throw()
+ bitmap_allocator() _GLIBCXX_USE_NOEXCEPT
{ }
- bitmap_allocator(const bitmap_allocator&)
+ bitmap_allocator(const bitmap_allocator&) _GLIBCXX_USE_NOEXCEPT
{ }
template<typename _Tp1>
- bitmap_allocator(const bitmap_allocator<_Tp1>&) throw()
+ bitmap_allocator(const bitmap_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT
{ }
- ~bitmap_allocator() throw()
+ ~bitmap_allocator() _GLIBCXX_USE_NOEXCEPT
{ }
- pointer
+ _GLIBCXX_NODISCARD pointer
allocate(size_type __n)
{
- if (__builtin_expect(__n > this->max_size(), false))
+ if (__n > this->max_size())
std::__throw_bad_alloc();
+#if __cpp_aligned_new
+ if (alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+ {
+ const size_type __b = __n * sizeof(value_type);
+ std::align_val_t __al = std::align_val_t(alignof(value_type));
+ return static_cast<pointer>(::operator new(__b, __al));
+ }
+#endif
+
if (__builtin_expect(__n == 1, true))
return this->_M_allocate_single_object();
else
}
}
- pointer
+ _GLIBCXX_NODISCARD pointer
allocate(size_type __n, typename bitmap_allocator<void>::const_pointer)
{ return allocate(__n); }
{
if (__builtin_expect(__p != 0, true))
{
+#if __cpp_aligned_new
+ // Types with extended alignment are handled by operator delete.
+ if (alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+ {
+ ::operator delete(__p, std::align_val_t(alignof(value_type)));
+ return;
+ }
+#endif
+
if (__builtin_expect(__n == 1, true))
this->_M_deallocate_single_object(__p);
else
}
pointer
- address(reference __r) const
- { return &__r; }
+ address(reference __r) const _GLIBCXX_NOEXCEPT
+ { return std::__addressof(__r); }
const_pointer
- address(const_reference __r) const
- { return &__r; }
+ address(const_reference __r) const _GLIBCXX_NOEXCEPT
+ { return std::__addressof(__r); }
size_type
- max_size() const throw()
+ max_size() const _GLIBCXX_USE_NOEXCEPT
{ return size_type(-1) / sizeof(value_type); }
+#if __cplusplus >= 201103L
+ template<typename _Up, typename... _Args>
+ void
+ construct(_Up* __p, _Args&&... __args)
+ { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
+
+ template<typename _Up>
+ void
+ destroy(_Up* __p)
+ { __p->~_Up(); }
+#else
void
construct(pointer __p, const_reference __data)
- { ::new(__p) value_type(__data); }
+ { ::new((void *)__p) value_type(__data); }
void
destroy(pointer __p)
{ __p->~value_type(); }
+#endif
};
template<typename _Tp1, typename _Tp2>
const bitmap_allocator<_Tp2>&) throw()
{ return true; }
+#if __cpp_impl_three_way_comparison < 201907L
template<typename _Tp1, typename _Tp2>
bool
operator!=(const bitmap_allocator<_Tp1>&,
const bitmap_allocator<_Tp2>&) throw()
- { return false; }
+ { return false; }
+#endif
// Static member definitions.
template<typename _Tp>
bitmap_allocator<_Tp>::_S_mem_blocks;
template<typename _Tp>
- size_t bitmap_allocator<_Tp>::_S_block_size =
- 2 * size_t(balloc::bits_per_block);
+ std::size_t bitmap_allocator<_Tp>::_S_block_size
+ = 2 * std::size_t(__detail::bits_per_block);
template<typename _Tp>
- typename __gnu_cxx::bitmap_allocator<_Tp>::_BPVector::size_type
+ typename bitmap_allocator<_Tp>::_BPVector::size_type
bitmap_allocator<_Tp>::_S_last_dealloc_index = 0;
template<typename _Tp>
- __gnu_cxx::balloc::_Bitmap_counter
- <typename bitmap_allocator<_Tp>::_Alloc_block*>
+ __detail::_Bitmap_counter
+ <typename bitmap_allocator<_Tp>::_Alloc_block*>
bitmap_allocator<_Tp>::_S_last_request(_S_mem_blocks);
#if defined __GTHREADS
template<typename _Tp>
- __gnu_cxx::_Mutex
+ typename bitmap_allocator<_Tp>::__mutex_type
bitmap_allocator<_Tp>::_S_mut;
#endif
-_GLIBCXX_END_NAMESPACE
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace __gnu_cxx
#endif
-
-// LocalWords: namespace GTHREADS bool const gthread endif Mutex mutex