diff options
author | Benjamin Kosnik <bkoz@redhat.com> | 2003-12-23 07:24:57 +0000 |
---|---|---|
committer | Benjamin Kosnik <bkoz@gcc.gnu.org> | 2003-12-23 07:24:57 +0000 |
commit | d38d4e5d1800457ad097cb5e6dc35387998e6efa (patch) | |
tree | de3ca351c848fcc5c05f6ece2f1559423a3a5fc1 /libstdc++-v3 | |
parent | cbf6e52aa53df8528eb21cff83631a0523cae79c (diff) | |
download | gcc-d38d4e5d1800457ad097cb5e6dc35387998e6efa.zip gcc-d38d4e5d1800457ad097cb5e6dc35387998e6efa.tar.gz gcc-d38d4e5d1800457ad097cb5e6dc35387998e6efa.tar.bz2 |
new_allocator.h (new_allocator): Proper allocator class.
2003-12-23 Benjamin Kosnik <bkoz@redhat.com>
* include/ext/new_allocator.h (new_allocator): Proper allocator class.
(__new_alloc): Delete.
* include/ext/malloc_allocator.h (malloc_allocator): Same.
(__malloc_alloc): Delete.
* include/ext/mt_allocator.h: Same, but weakly.
* include/ext/debug_allocator.h: Convert to the new style.
* include/ext/pool_allocator.h: Use global new and delete directly.
* include/backward/alloc.h: Don't inject malloc_allocator, or
debug_allocator.
* testsuite/ext/allocators.cc: Minimal fixups for usage of new
classes. Comment out tests with __pool_alloc for now.
* testsuite/performance/allocator.cc: Same.
From-SVN: r74965
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 15 | ||||
-rw-r--r-- | libstdc++-v3/include/backward/alloc.h | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/debug_allocator.h | 94 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/malloc_allocator.h | 177 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/mt_allocator.h | 262 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/new_allocator.h | 79 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/pool_allocator.h | 15 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/ext/allocators.cc | 50 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/performance/allocator.cc | 6 |
9 files changed, 332 insertions, 370 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 666f7806..9c8048d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,18 @@ +2003-12-23 Benjamin Kosnik <bkoz@redhat.com> + + * include/ext/new_allocator.h (new_allocator): Proper allocator class. + (__new_alloc): Delete. + * include/ext/malloc_allocator.h (malloc_allocator): Same. + (__malloc_alloc): Delete. + * include/ext/mt_allocator.h: Same, but weakly. + * include/ext/debug_allocator.h: Convert to the new style. + * include/ext/pool_allocator.h: Use global new and delete directly. + * include/backward/alloc.h: Don't inject malloc_allocator, or + debug_allocator. + * testsuite/ext/allocators.cc: Minimal fixups for usage of new + classes. Comment out tests with __pool_alloc for now. + * testsuite/performance/allocator.cc: Same. + 2003-12-22 Matt Austern <austern@apple.com> * include/bits/stl_bvector.h (_Bvector_alloc_base): Eliminate. diff --git a/libstdc++-v3/include/backward/alloc.h b/libstdc++-v3/include/backward/alloc.h index 96cdd54..ad9e4e5 100644 --- a/libstdc++-v3/include/backward/alloc.h +++ b/libstdc++-v3/include/backward/alloc.h @@ -46,11 +46,7 @@ #include "backward_warning.h" #include <bits/c++config.h> #include <bits/allocator.h> -#include <ext/debug_allocator.h> -#include <ext/malloc_allocator.h> -using __gnu_cxx::__malloc_alloc; -using __gnu_cxx::__debug_alloc; using __gnu_cxx::__pool_alloc; using std::__alloc; using std::__simple_alloc; diff --git a/libstdc++-v3/include/ext/debug_allocator.h b/libstdc++-v3/include/ext/debug_allocator.h index 7bab02e..e744ab6 100644 --- a/libstdc++-v3/include/ext/debug_allocator.h +++ b/libstdc++-v3/include/ext/debug_allocator.h @@ -48,92 +48,58 @@ #ifndef _DEBUG_ALLOCATOR_H #define _DEBUG_ALLOCATOR_H 1 -#include <bits/allocator_traits.h> +#include <memory> namespace __gnu_cxx { /** - * @if maint - * An adaptor for an underlying allocator (_Alloc) to check the size - * arguments for debugging. + * @brief A meta-allocator with debugging bits, as per [20.4]. * - * "There is some evidence that this can confuse Purify." - SGI comment + * This is precisely the allocator defined in the C++ Standard. + * - all allocation calls operator new + * - all deallocation calls operator delete * - * This adaptor is "SGI" style. The _Alloc parameter must also be "SGI". - * @endif * (See @link Allocators allocators info @endlink for more.) */ template<typename _Alloc> - class __debug_alloc + class debug_allocator { + public: + typedef typename _Alloc::size_type size_type; + typedef typename _Alloc::difference_type difference_type; + typedef typename _Alloc::pointer pointer; + typedef typename _Alloc::const_pointer const_pointer; + typedef typename _Alloc::reference reference; + typedef typename _Alloc::const_reference const_reference; + typedef typename _Alloc::value_type value_type; + private: // Size of space used to store size. Note that this must be // large enough to preserve alignment. - enum {_S_extra = 8}; + const size_t _M_extra; + + _Alloc _M_allocator; public: - static void* - allocate(size_t __n) + debug_allocator() : _M_extra(8) { } + + pointer + allocate(size_type __n, std::allocator<void>::const_pointer = 0) { - char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra); - *(size_t*)__result = __n; - return __result + (int) _S_extra; + pointer __result = _M_allocator.allocate(__n + _M_extra); + *__result = __n; + return __result + _M_extra; } - static void - deallocate(void* __p, size_t __n) + void + deallocate(pointer __p, size_type __n) { - char* __real_p = (char*)__p - (int) _S_extra; - if (*(size_t*)__real_p != __n) + pointer __real_p = __p - _M_extra; + if (*__real_p != __n) abort(); - _Alloc::deallocate(__real_p, __n + (int) _S_extra); + _M_allocator.deallocate(__real_p, __n + _M_extra); } }; - - //@{ - /** Comparison operators for all of the predifined SGI-style allocators. - * This ensures that __allocator<malloc_alloc> (for example) will work - * correctly. As required, all allocators compare equal. - */ - template<typename _Alloc> - inline bool - operator==(const __debug_alloc<_Alloc>&, const __debug_alloc<_Alloc>&) - { return true; } - - template<typename _Alloc> - inline bool - operator!=(const __debug_alloc<_Alloc>&, const __debug_alloc<_Alloc>&) - { return false; } - //@} } // namespace __gnu_cxx -namespace std -{ - //@{ - /// Versions for the predefined "SGI" style allocators. - template<typename _Tp, typename _Alloc> - struct _Alloc_traits<_Tp, __gnu_cxx::__debug_alloc<_Alloc> > - { - static const bool _S_instanceless = true; - typedef __gnu_cxx::__debug_alloc<_Alloc> base_alloc_type; - typedef __simple_alloc<_Tp, base_alloc_type> _Alloc_type; - typedef __allocator<_Tp, base_alloc_type> allocator_type; - }; - //@} - - //@{ - /// Versions for the __allocator adaptor used with the predefined - /// "SGI" style allocators. - template<typename _Tp, typename _Tp1, typename _Alloc> - struct _Alloc_traits<_Tp, __allocator<_Tp1, - __gnu_cxx::__debug_alloc<_Alloc> > > - { - static const bool _S_instanceless = true; - typedef __gnu_cxx::__debug_alloc<_Alloc> base_alloc_type; - typedef __simple_alloc<_Tp, base_alloc_type> _Alloc_type; - typedef __allocator<_Tp, base_alloc_type> allocator_type; - }; - //@} -} // namespace std - #endif diff --git a/libstdc++-v3/include/ext/malloc_allocator.h b/libstdc++-v3/include/ext/malloc_allocator.h index b0a837b..5545a58 100644 --- a/libstdc++-v3/include/ext/malloc_allocator.h +++ b/libstdc++-v3/include/ext/malloc_allocator.h @@ -1,4 +1,4 @@ -// Allocators -*- C++ -*- +// Allocator that wraps "C" malloc -*- C++ -*- // Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. // @@ -27,137 +27,78 @@ // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. -/* - * Copyright (c) 1996-1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file ext/debug_allocator.h - * This file is a GNU extension to the Standard C++ Library. - * You should only include this header if you are using GCC 3 or later. - */ - #ifndef _MALLOC_ALLOCATOR_H #define _MALLOC_ALLOCATOR_H 1 -#include <bits/allocator_traits.h> +#include <new> +#include <memory> namespace __gnu_cxx { /** - * @if maint - * A malloc-based allocator. Typically slower than the - * __pool_alloc (below). Typically thread-safe and more - * storage efficient. The template argument is unused and is only present - * to permit multiple instantiations (but see __pool_alloc - * for caveats). "SGI" style, plus __set_malloc_handler for OOM conditions. - * @endif + * @brief An allocator that uses malloc + * + * This is precisely the allocator defined in the C++ Standard. + * - all allocation calls malloc + * - all deallocation calls free + * * (See @link Allocators allocators info @endlink for more.) */ - template<int __inst> - class __malloc_alloc + template<typename _Tp> + class malloc_allocator { - private: - static void* _S_oom_malloc(size_t); - static void (* __malloc_alloc_oom_handler)(); - public: - static void* - allocate(size_t __n) - { - void* __result = malloc(__n); - if (__builtin_expect(__result == 0, 0)) - __result = _S_oom_malloc(__n); - return __result; - } - - static void - deallocate(void* __p, size_t /* __n */) - { free(__p); } - - static void (* __set_malloc_handler(void (*__f)()))() - { - void (* __old)() = __malloc_alloc_oom_handler; - __malloc_alloc_oom_handler = __f; - return __old; - } - }; + 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; - // malloc_alloc out-of-memory handling - template<int __inst> - void (* __malloc_alloc<__inst>::__malloc_alloc_oom_handler)() = 0; + template<typename _Tp1> + struct rebind + { typedef malloc_allocator<_Tp1> other; }; - template<int __inst> - void* - __malloc_alloc<__inst>:: - _S_oom_malloc(size_t __n) - { - void (* __my_malloc_handler)(); - void* __result; - - for (;;) - { - __my_malloc_handler = __malloc_alloc_oom_handler; - if (__builtin_expect(__my_malloc_handler == 0, 0)) - __throw_bad_alloc(); - (*__my_malloc_handler)(); - __result = malloc(__n); - if (__result) - return __result; - } - } - //@{ - /** Comparison operators for all of the predifined SGI-style allocators. - * This ensures that __allocator<malloc_alloc> (for example) will work - * correctly. As required, all allocators compare equal. - */ - template<int inst> - inline bool - operator==(const __malloc_alloc<inst>&, const __malloc_alloc<inst>&) - { return true; } - - template<int __inst> - inline bool - operator!=(const __malloc_alloc<__inst>&, const __malloc_alloc<__inst>&) - { return false; } - //@} -} // namespace __gnu_cxx + malloc_allocator() throw() { } -namespace std -{ - //@{ - /// Versions for the predefined "SGI" style allocators. - template<typename _Tp, int __inst> - struct _Alloc_traits<_Tp, __gnu_cxx::__malloc_alloc<__inst> > - { - static const bool _S_instanceless = true; - typedef __gnu_cxx:: __malloc_alloc<__inst> base_alloc_type; - typedef __simple_alloc<_Tp, base_alloc_type> _Alloc_type; - typedef __allocator<_Tp, base_alloc_type> allocator_type; - }; - //@} - - //@{ - /// Versions for the __allocator adaptor used with the predefined - /// "SGI" style allocators. - template<typename _Tp, typename _Tp1, int __inst> - struct _Alloc_traits<_Tp, __allocator<_Tp1, - __gnu_cxx::__malloc_alloc<__inst> > > - { - static const bool _S_instanceless = true; - typedef __gnu_cxx:: __malloc_alloc<__inst> base_alloc_type; - typedef __simple_alloc<_Tp, base_alloc_type> _Alloc_type; - typedef __allocator<_Tp, base_alloc_type> allocator_type; + malloc_allocator(const malloc_allocator&) throw() { } + + template<typename _Tp1> + malloc_allocator(const malloc_allocator<_Tp1>&) throw() { } + + ~malloc_allocator() throw() { } + + pointer + address(reference __x) const { return &__x; } + + const_pointer + address(const_reference __x) const { return &__x; } + + // NB: __n is permitted to be 0. The C++ standard says nothing + // about what the return value is when __n == 0. + pointer + allocate(size_type __n, std::allocator<void>::const_pointer __h = 0) + { return static_cast<_Tp*>(malloc(__n * sizeof(_Tp))); } + + // __p is not permitted to be a null pointer. + void + deallocate(pointer __p, size_type __n) + { free(static_cast<void*>(__p)); } + + size_type + max_size() const throw() + { return size_t(-1) / sizeof(_Tp); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 402. wrong new expression in [some_] allocator::construct + void + construct(pointer __p, const _Tp& __val) + { *__p = __val; } + + void + destroy(pointer __p) { __p->~_Tp(); } }; - //@} -} // namespace std +} // namespace __gnu_cxx #endif diff --git a/libstdc++-v3/include/ext/mt_allocator.h b/libstdc++-v3/include/ext/mt_allocator.h index 42c804f..ec77192 100644 --- a/libstdc++-v3/include/ext/mt_allocator.h +++ b/libstdc++-v3/include/ext/mt_allocator.h @@ -35,32 +35,83 @@ #ifndef _MT_ALLOCATOR_H #define _MT_ALLOCATOR_H 1 +#include <new> +#include <memory> #include <cstdlib> #include <bits/functexcept.h> #include <bits/gthr.h> #include <bits/atomicity.h> -#include <bits/allocator_traits.h> namespace __gnu_cxx { - -/** - * This is a fixed size (power of 2) allocator which - when compiled - * with thread support - will maintain one freelist per size per thread - * plus a "global" one. Steps are taken to limit the per thread freelist - * sizes (by returning excess back to "global"). - * - * Usage examples: - * @code - * vector<int, __gnu_cxx::__mt_alloc<0> > v1; - * - * typedef std::__allocator<char, __gnu_cxx::__mt_alloc<0> > string_alloc; - * std::basic_string<char, std::char_traits<char>, string_alloc> s1; - * @endcode - */ - template<int __inst> + /** + * This is a fixed size (power of 2) allocator which - when + * compiled with thread support - will maintain one freelist per + * size per thread plus a "global" one. Steps are taken to limit + * the per thread freelist sizes (by returning excess back to + * "global"). + * + * Usage examples: + * @code + * vector<int, __gnu_cxx::__mt_alloc<int> > v1; + * + * typedef __gnu_cxx::__mt_alloc<char> > string_allocator; + * std::basic_string<char, std::char_traits<char>, string_allocator> s1; + * @endcode + */ + template<typename _Tp> class __mt_alloc { + 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; + + template<typename _Tp1> + struct rebind + { typedef __mt_alloc<_Tp1> other; }; + + __mt_alloc() throw() + { + // XXX + } + + __mt_alloc(const __mt_alloc&) throw() + { + // XXX + } + + template<typename _Tp1> + __mt_alloc(const __mt_alloc<_Tp1>&) throw() + { + // XXX + } + + ~__mt_alloc() throw() { } + + pointer + address(reference __x) const { return &__x; } + + const_pointer + address(const_reference __x) const { return &__x; } + + size_type + max_size() const throw() + { return size_t(-1) / sizeof(_Tp); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 402. wrong new expression in [some_] allocator::construct + void + construct(pointer __p, const _Tp& __val) + { ::new(__p) _Tp(__val); } + + void + destroy(pointer __p) { __p->~_Tp(); } + private: /* * We need to create the initial lists and set up some variables @@ -174,23 +225,21 @@ namespace __gnu_cxx static bin_record* _S_bin; public: - static void* - allocate(size_t __n) + pointer + allocate(size_t __n, std::allocator<void>::const_pointer __h = 0) { - /* * Requests larger than _S_max_bytes are handled by - * malloc/free directly + * new/delete directly */ if (__n > _S_max_bytes) { - void* __ret = malloc(__n); + void* __ret = malloc(__n * sizeof(_Tp)); if (!__ret) __throw_bad_alloc(); - - return __ret; + return static_cast<_Tp*>(__ret); } - + /* * Although the test in __gthread_once() would suffice, we * wrap test of the once condition in our own unlocked @@ -306,8 +355,8 @@ namespace __gnu_cxx __throw_bad_alloc(); size_t bin_t = 1 << bin; - size_t block_count = - _S_chunk_size / (bin_t + sizeof(block_record)); + size_t block_count = + _S_chunk_size / (bin_t + sizeof(block_record)); _S_bin[bin].free[0] = block_count; @@ -349,11 +398,11 @@ namespace __gnu_cxx _S_bin[bin].used[thread_id]++; } - return (void*)((char*)block + sizeof(block_record)); + return static_cast<_Tp*>(static_cast<void*>((char*)block + sizeof(block_record))); } - static void - deallocate(void* __p, size_t __n) + void + deallocate(pointer __p, size_type __n) { /* * Requests larger than _S_max_bytes are handled by @@ -363,7 +412,7 @@ namespace __gnu_cxx { free(__p); return; - } + } /* * Round up to power of 2 and figure out which bin to use @@ -482,9 +531,9 @@ namespace __gnu_cxx } }; - template<int __inst> + template<typename _Tp> void - __mt_alloc<__inst>:: + __mt_alloc<_Tp>:: _S_init() { /* @@ -530,7 +579,7 @@ namespace __gnu_cxx #ifdef __GTHREADS if (__gthread_active_p()) { - _S_thread_freelist_first = + _S_thread_freelist_first = (thread_record*)malloc(sizeof(thread_record) * _S_max_threads); if (!_S_thread_freelist_first) @@ -543,8 +592,8 @@ namespace __gnu_cxx size_t i; for (i = 1; i < _S_max_threads; i++) { - _S_thread_freelist_first[i - 1].next = - &_S_thread_freelist_first[i]; + _S_thread_freelist_first[i - 1].next = + &_S_thread_freelist_first[i]; _S_thread_freelist_first[i - 1].id = i; } @@ -578,42 +627,34 @@ namespace __gnu_cxx if (!_S_bin) __throw_bad_alloc(); - for (size_t bin = 0; bin < _S_no_of_bins; bin++) + for (size_t bin = 0; bin < _S_no_of_bins; bin++) { - _S_bin[bin].first = (block_record**) - malloc(sizeof(block_record*) * (_S_max_threads + 1)); + std::size_t __n = _S_max_threads + 1; + + _S_bin[bin].first = (block_record**) + malloc(sizeof(block_record*) * __n); if (!_S_bin[bin].first) __throw_bad_alloc(); - _S_bin[bin].last = (block_record**) - malloc(sizeof(block_record*) * (_S_max_threads + 1)); + _S_bin[bin].last = (block_record**) + malloc(sizeof(block_record*) * __n); if (!_S_bin[bin].last) __throw_bad_alloc(); - _S_bin[bin].free = (size_t*) - malloc(sizeof(size_t) * (_S_max_threads + 1)); + _S_bin[bin].free = (size_t*) malloc(sizeof(size_t) * __n); if (!_S_bin[bin].free) __throw_bad_alloc(); - _S_bin[bin].used = (size_t*) - malloc(sizeof(size_t) * (_S_max_threads + 1)); + _S_bin[bin].used = (size_t*) malloc(sizeof(size_t) * __n); if (!_S_bin[bin].used) __throw_bad_alloc(); - /* - * Ugly workaround of what at the time of writing seems to be - * a parser problem - see PR c++/9779 for more info. - */ #ifdef __GTHREADS - size_t s = sizeof(__gthread_mutex_t); - _S_bin[bin].mutex = (__gthread_mutex_t*)malloc(s); - - if (!_S_bin[bin].mutex) - __throw_bad_alloc(); + _S_bin[bin].mutex =(__gthread_mutex_t*) malloc(sizeof(__gthread_mutex_t)); #ifdef __GTHREAD_MUTEX_INIT { @@ -635,23 +676,17 @@ namespace __gnu_cxx } } - _S_initialized = true; + _S_initialized = true; } #ifdef __GTHREADS - template<int __inst> + template<typename _Tp> void - __mt_alloc<__inst>:: + __mt_alloc<_Tp>:: _S_thread_key_destr(void* freelist_pos) { /* - * This is due to the ugly workaround mentioned in _S_init() - */ - if (freelist_pos == NULL) - return; - - /* - * If the thread - when it dies - still have records on its + * If the thread - when it dies - still has records on its * freelist we return them to the global pool here. */ for (size_t bin = 0; bin < _S_no_of_bins; bin++) @@ -662,7 +697,6 @@ namespace __gnu_cxx if (block != NULL) { __gthread_mutex_lock(_S_bin[bin].mutex); - while (block != NULL) { if (_S_bin[bin].first[0] == NULL) @@ -671,14 +705,11 @@ namespace __gnu_cxx _S_bin[bin].last[0]->next = block; _S_bin[bin].last[0] = block; - block = block->next; - _S_bin[bin].free[0]++; } _S_bin[bin].last[0]->next = NULL; - __gthread_mutex_unlock(_S_bin[bin].mutex); } } @@ -687,18 +718,15 @@ namespace __gnu_cxx * Return this thread id record to thread_freelist */ __gthread_mutex_lock(&_S_thread_freelist_mutex); - _S_thread_freelist_last->next = (thread_record*)freelist_pos; _S_thread_freelist_last = (thread_record*)freelist_pos; _S_thread_freelist_last->next = NULL; - __gthread_mutex_unlock(&_S_thread_freelist_mutex); - } - template<int __inst> + template<typename _Tp> size_t - __mt_alloc<__inst>:: + __mt_alloc<_Tp>:: _S_get_thread_id() { /* @@ -714,16 +742,14 @@ namespace __gnu_cxx if ((freelist_pos = (thread_record*)__gthread_getspecific(_S_thread_key)) == NULL) { - __gthread_mutex_lock(&_S_thread_freelist_mutex); - /* * Since _S_max_threads must be larger than the * theoretical max number of threads of the OS the list * can never be empty. */ + __gthread_mutex_lock(&_S_thread_freelist_mutex); freelist_pos = _S_thread_freelist_first; _S_thread_freelist_first = _S_thread_freelist_first->next; - __gthread_mutex_unlock(&_S_thread_freelist_mutex); __gthread_setspecific(_S_thread_key, (void*)freelist_pos); @@ -754,23 +780,23 @@ namespace __gnu_cxx return 0; } - template<int __inst> __gthread_once_t - __mt_alloc<__inst>::_S_once_mt = __GTHREAD_ONCE_INIT; + template<typename _Tp> __gthread_once_t + __mt_alloc<_Tp>::_S_once_mt = __GTHREAD_ONCE_INIT; #endif - template<int __inst> bool - __mt_alloc<__inst>::_S_initialized = false; + template<typename _Tp> bool + __mt_alloc<_Tp>::_S_initialized = false; - template<int __inst> typename __mt_alloc<__inst>::binmap_type* - __mt_alloc<__inst>::_S_binmap = NULL; + template<typename _Tp> typename __mt_alloc<_Tp>::binmap_type* + __mt_alloc<_Tp>::_S_binmap = NULL; /* * Allocation requests (after round-up to power of 2) below this * value will be handled by the allocator. A raw malloc/free() call * will be used for requests larger than this value. */ - template<int __inst> size_t - __mt_alloc<__inst>::_S_max_bytes = 128; + template<typename _Tp> size_t + __mt_alloc<_Tp>::_S_max_bytes = 128; /* * In order to avoid fragmenting and minimize the number of malloc() @@ -779,21 +805,21 @@ namespace __gnu_cxx * choosen the value below. See * http://gcc.gnu.org/ml/libstdc++/2001-07/msg00077.html */ - template<int __inst> size_t - __mt_alloc<__inst>::_S_chunk_size = 4096 - 4 * sizeof(void*); + template<typename _Tp> size_t + __mt_alloc<_Tp>::_S_chunk_size = 4096 - 4 * sizeof(void*); /* * The maximum number of supported threads. Our Linux 2.4.18 reports * 4070 in /proc/sys/kernel/threads-max */ - template<int __inst> size_t - __mt_alloc<__inst>::_S_max_threads = 4096; + template<typename _Tp> size_t + __mt_alloc<_Tp>::_S_max_threads = 4096; /* * Actual value calculated in _S_init() */ - template<int __inst> size_t - __mt_alloc<__inst>::_S_no_of_bins = 1; + template<typename _Tp> size_t + __mt_alloc<_Tp>::_S_no_of_bins = 1; /* * Each time a deallocation occurs in a threaded application we make @@ -802,63 +828,31 @@ namespace __gnu_cxx * more than _S_freelist_headroom % of the freelist, we move these * records back to the global pool. */ - template<int __inst> size_t - __mt_alloc<__inst>::_S_freelist_headroom = 10; + template<typename _Tp> size_t + __mt_alloc<_Tp>::_S_freelist_headroom = 10; /* * Actual initialization in _S_init() */ #ifdef __GTHREADS - template<int __inst> typename __mt_alloc<__inst>::thread_record* - __mt_alloc<__inst>::_S_thread_freelist_first = NULL; + template<typename _Tp> typename __mt_alloc<_Tp>::thread_record* + __mt_alloc<_Tp>::_S_thread_freelist_first = NULL; - template<int __inst> typename __mt_alloc<__inst>::thread_record* - __mt_alloc<__inst>::_S_thread_freelist_last = NULL; + template<typename _Tp> typename __mt_alloc<_Tp>::thread_record* + __mt_alloc<_Tp>::_S_thread_freelist_last = NULL; - template<int __inst> __gthread_mutex_t - __mt_alloc<__inst>::_S_thread_freelist_mutex = __GTHREAD_MUTEX_INIT; + template<typename _Tp> __gthread_mutex_t + __mt_alloc<_Tp>::_S_thread_freelist_mutex = __GTHREAD_MUTEX_INIT; /* * Actual initialization in _S_init() */ - template<int __inst> __gthread_key_t - __mt_alloc<__inst>::_S_thread_key; + template<typename _Tp> __gthread_key_t + __mt_alloc<_Tp>::_S_thread_key; #endif - template<int __inst> typename __mt_alloc<__inst>::bin_record* - __mt_alloc<__inst>::_S_bin = NULL; - - template<int __inst> - inline bool - operator==(const __mt_alloc<__inst>&, const __mt_alloc<__inst>&) - { return true; } - - template<int __inst> - inline bool - operator!=(const __mt_alloc<__inst>&, const __mt_alloc<__inst>&) - { return false; } + template<typename _Tp> typename __mt_alloc<_Tp>::bin_record* + __mt_alloc<_Tp>::_S_bin = NULL; } // namespace __gnu_cxx -namespace std -{ - template<typename _Tp, int __inst> - struct _Alloc_traits<_Tp, __gnu_cxx::__mt_alloc<__inst> > - { - static const bool _S_instanceless = true; - typedef __gnu_cxx:: __mt_alloc<__inst> base_alloc_type; - typedef __simple_alloc<_Tp, base_alloc_type> _Alloc_type; - typedef __allocator<_Tp, base_alloc_type> allocator_type; - }; - - template<typename _Tp, typename _Tp1, int __inst> - struct _Alloc_traits<_Tp, - __allocator<_Tp1, __gnu_cxx::__mt_alloc<__inst> > > - { - static const bool _S_instanceless = true; - typedef __gnu_cxx:: __mt_alloc<__inst> base_alloc_type; - typedef __simple_alloc<_Tp, base_alloc_type> _Alloc_type; - typedef __allocator<_Tp, base_alloc_type> allocator_type; - }; -} // namespace std - #endif diff --git a/libstdc++-v3/include/ext/new_allocator.h b/libstdc++-v3/include/ext/new_allocator.h index 794751d..6c8ca63 100644 --- a/libstdc++-v3/include/ext/new_allocator.h +++ b/libstdc++-v3/include/ext/new_allocator.h @@ -1,4 +1,4 @@ -// Allocators -*- C++ -*- +// Allocator that wraps operator new -*- C++ -*- // Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. // @@ -35,24 +35,69 @@ namespace __gnu_cxx { /** - * @if maint - * A new-based allocator, as required by the standard. Allocation and - * deallocation forward to global new and delete. "SGI" style, minus - * reallocate(). - * @endif + * @brief An allocator that uses global new, as per [20.4]. + * + * This is precisely the allocator defined in the C++ Standard. + * - all allocation calls operator new + * - all deallocation calls operator delete + * * (See @link Allocators allocators info @endlink for more.) */ - class __new_alloc - { - public: - static void* - allocate(size_t __n) - { return ::operator new(__n); } - - static void - deallocate(void* __p, size_t) - { ::operator delete(__p); } - }; + template<typename _Tp> + class new_allocator + { + 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; + + template<typename _Tp1> + struct rebind + { typedef new_allocator<_Tp1> other; }; + + new_allocator() throw() { } + + new_allocator(const new_allocator&) throw() { } + + template<typename _Tp1> + new_allocator(const new_allocator<_Tp1>&) throw() { } + + ~new_allocator() throw() { } + + pointer + address(reference __x) const { return &__x; } + + const_pointer + address(const_reference __x) const { return &__x; } + + // NB: __n is permitted to be 0. The C++ standard says nothing + // about what the return value is when __n == 0. + pointer + allocate(size_type __n, allocator<void>::const_pointer __h = 0) + { return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); } + + // __p is not permitted to be a null pointer. + void + deallocate(pointer __p, size_type __n) + { ::operator delete(__p); } + + size_type + max_size() const throw() + { return size_t(-1) / sizeof(_Tp); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 402. wrong new expression in [some_] allocator::construct + void + construct(pointer __p, const _Tp& __val) + { ::new(__p) _Tp(__val); } + + void + destroy(pointer __p) { __p->~_Tp(); } + }; } // namespace __gnu_cxx #endif diff --git a/libstdc++-v3/include/ext/pool_allocator.h b/libstdc++-v3/include/ext/pool_allocator.h index 15e1eb4..cb2df02 100644 --- a/libstdc++-v3/include/ext/pool_allocator.h +++ b/libstdc++-v3/include/ext/pool_allocator.h @@ -44,15 +44,14 @@ * This file is a GNU extension to the Standard C++ Library. * You should only include this header if you are using GCC 3 or later. */ - #ifndef _POOL_ALLOCATOR_H #define _POOL_ALLOCATOR_H 1 +#include <new> #include <bits/functexcept.h> #include <bits/stl_threads.h> #include <bits/atomicity.h> #include <bits/allocator_traits.h> -#include <ext/new_allocator.h> namespace __gnu_cxx { @@ -65,9 +64,9 @@ namespace __gnu_cxx * when in default high-speed pool mode). * * Important implementation properties: - * 0. If globally mandated, then allocate objects from __new_alloc + * 0. If globally mandated, then allocate objects from new * 1. If the clients request an object of size > _S_max_bytes, the resulting - * object will be obtained directly from __new_alloc + * object will be obtained directly from new * 2. In all other cases, we allocate an object of size exactly * _S_round_up(requested_size). Thus the client has enough size * information that we can return the object to the proper free list @@ -201,7 +200,7 @@ namespace __gnu_cxx ((_Obj*)(void*)_S_start_free)->_M_free_list_link = *__free_list; *__free_list = (_Obj*)(void*)_S_start_free; } - _S_start_free = (char*) __new_alloc::allocate(__bytes_to_get); + _S_start_free = new char[__bytes_to_get]; if (_S_start_free == 0) { size_t __i; @@ -226,7 +225,7 @@ namespace __gnu_cxx } } _S_end_free = 0; // In case of exception. - _S_start_free = (char*)__new_alloc::allocate(__bytes_to_get); + _S_start_free = new char[__bytes_to_get]; // This should either throw an exception or remedy the situation. // Thus we assume it succeeded. } @@ -291,7 +290,7 @@ namespace __gnu_cxx } if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0)) - __ret = __new_alloc::allocate(__n); + __ret = new char[__n]; else { _Obj* volatile* __free_list = _S_free_list + _S_freelist_index(__n); @@ -318,7 +317,7 @@ namespace __gnu_cxx __pool_alloc<__threads, __inst>::deallocate(void* __p, size_t __n) { if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0)) - __new_alloc::deallocate(__p, __n); + delete [] __p; else { _Obj* volatile* __free_list = _S_free_list + _S_freelist_index(__n); diff --git a/libstdc++-v3/testsuite/ext/allocators.cc b/libstdc++-v3/testsuite/ext/allocators.cc index 85205d5..7e4e9f9 100644 --- a/libstdc++-v3/testsuite/ext/allocators.cc +++ b/libstdc++-v3/testsuite/ext/allocators.cc @@ -22,25 +22,23 @@ #include <cstdlib> #include <memory> -#include <ext/pool_allocator.h> +//#include <ext/pool_allocator.h> #include <ext/debug_allocator.h> #include <ext/malloc_allocator.h> #include <testsuite_hooks.h> -using __gnu_cxx::__malloc_alloc; -using __gnu_cxx::__debug_alloc; -using __gnu_cxx::__pool_alloc; +using __gnu_cxx::malloc_allocator; +using __gnu_cxx::debug_allocator; -template class __malloc_alloc<3>; -template class __debug_alloc<__malloc_alloc<3> >; -template class __pool_alloc<true, 3>; -template class __pool_alloc<false, 3>; -struct big -{ - long f[15]; -}; +template class malloc_allocator<int>; +template class debug_allocator<malloc_allocator<int> >; +#if 0 +using __gnu_cxx::__pool_alloc; +template class __pool_alloc<true, 3>; +template class __pool_alloc<false, 3>; +#endif bool new_called; bool delete_called; @@ -69,31 +67,39 @@ void check_allocator() delete_called = false; requested = 0; - std::__allocator<big, Alloc> a; - big *p = a.allocate(10); + Alloc a; + typename Alloc::pointer p = a.allocate(10); if (uses_global_new_and_delete) VERIFY( requested >= (10 * 15 * sizeof(long)) ); - // Touch the far end of supposedly-allocated memory to check that we got - // all of it. Why "3"? Because it's my favorite integer between e and pi. - p[9].f[14] = 3; VERIFY( new_called == uses_global_new_and_delete ); - a.deallocate(p,10); + a.deallocate(p, 10); VERIFY( delete_called == uses_global_new_and_delete ); } // These just help tracking down error messages. -void test01() { check_allocator<__malloc_alloc<3>, false>(); } -void test02() { check_allocator<__debug_alloc<__malloc_alloc<3> >, false>(); } -void test03() { check_allocator<__pool_alloc<true, 3>, true>(); } -void test04() { check_allocator<__pool_alloc<false, 3>, true>(); } +void test01() +{ check_allocator<malloc_allocator<int>, false>(); } + +void test02() +{ check_allocator<debug_allocator<malloc_allocator<int> >, false>(); } + +#if 0 +void test03() +{ check_allocator<__pool_alloc<true, 3>, true>(); } + +void test04() +{ check_allocator<__pool_alloc<false, 3>, true>(); } +#endif int main() { test01(); test02(); +#if 0 test03(); test04(); +#endif return 0; } diff --git a/libstdc++-v3/testsuite/performance/allocator.cc b/libstdc++-v3/testsuite/performance/allocator.cc index 4cd615e..e4a5ad4 100644 --- a/libstdc++-v3/testsuite/performance/allocator.cc +++ b/libstdc++-v3/testsuite/performance/allocator.cc @@ -61,7 +61,7 @@ #include <testsuite_performance.h> using namespace std; -using __gnu_cxx::__malloc_alloc; +using __gnu_cxx::malloc_allocator; using __gnu_cxx::__mt_alloc; /* @@ -155,7 +155,7 @@ test_ints_malloc_alloc(int iterations) tstart(); for(int i = 0; i < iterations; i++) { - vector<int, __malloc_alloc<0> > v1; + vector<int, malloc_allocator<int> > v1; for(int j = 0; j < insert_values; j++) { @@ -173,7 +173,7 @@ test_ints_mt_alloc(int iterations) tstart(); for(int i = 0; i < iterations; i++) { - vector<int, __mt_alloc<0> > v1; + vector<int, __mt_alloc<int> > v1; for(int j = 0; j < insert_values; j++) { |