aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog15
-rw-r--r--libstdc++-v3/include/backward/alloc.h4
-rw-r--r--libstdc++-v3/include/ext/debug_allocator.h94
-rw-r--r--libstdc++-v3/include/ext/malloc_allocator.h177
-rw-r--r--libstdc++-v3/include/ext/mt_allocator.h262
-rw-r--r--libstdc++-v3/include/ext/new_allocator.h79
-rw-r--r--libstdc++-v3/include/ext/pool_allocator.h15
-rw-r--r--libstdc++-v3/testsuite/ext/allocators.cc50
-rw-r--r--libstdc++-v3/testsuite/performance/allocator.cc6
9 files changed, 332 insertions, 370 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 666f7806bcc..9c8048dec24 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 96cdd543977..ad9e4e5bb3c 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 7bab02ebb31..e744ab61fae 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 b0a837bfd21..5545a58f8c9 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 42c804f610c..ec77192db26 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 794751d3c13..6c8ca6349ed 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 15e1eb45763..cb2df02997e 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 85205d53a7b..7e4e9f98aa4 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 4cd615e1a83..e4a5ad47766 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++)
{