diff options
author | bkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-06-11 15:52:11 +0000 |
---|---|---|
committer | bkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-06-11 15:52:11 +0000 |
commit | 93666440745e2eb59c05d7ca9c202f1d962fb2c7 (patch) | |
tree | 61989852861e8690ab5a873c759b5218e2280ca7 /libstdc++-v3 | |
parent | f7874cd76589d7ea2fd729e956469565069cdf76 (diff) | |
download | gcc-93666440745e2eb59c05d7ca9c202f1d962fb2c7.tar.gz |
2003-06-11 Benjamin Kosnik <bkoz@redhat.com>
* include/bits/stl_alloc.h (__debug_alloc): Move out.
(__malloc_alloc): Same.
(__pool_alloc): Same.
(__new_alloc): Same.
Rename to..
* include/bits/allocator.h: ...this.
* include/bits/stl_deque.h: Modify comment.
* include/bits/stl_tree.h: Modify include.
* include/std/std_memory.h: Same.
* include/ext/rope: Same.
* include/ext/slist: Same.
* include/std/std_vector.h: Same.
* include/std/std_stack.h: Same.
* include/std/std_queue.h: Same.
* include/std/std_list.h: Same.
* include/std/std_deque.h: Same.
* include/backward/alloc.h: Same.
* include/ext/debug_allocator.h: New.
* include/ext/malloc_allocator.h: New.
* include/ext/pool_allocator.h: New.
* include/ext/new_allocator.h: New.
* include/bits/pthread_allocimpl.h: Remove.
* include/bits/stl_pthread_alloc.h: Remove.
* include/Makefile.am (ext_headers): Add.
* include/Makefile.in: Regenerate.
* src/stl-inst.cc: Use __gnu_cxx namespace.
* src/stl-inst.cc: Move to...
* src/allocator-inst.cc: Here.
* src/Makefile.am (sources): Update.
* src/Makefile.in: Regenerate.
* config/linker-map.gnu: Remove __pool_alloc bits.
* testsuite/ext/headers.cc: Add.
* testsuite/ext/allocators.cc: Fixup.
2003-06-11 Stefan Olsson <stefan@snon.net>
Ola R�nnerup <fnolis@home.se>
* include/Makefile.am (ext_headers): Add.
* include/Makefile.in: Regenerate.
* include/ext/mt_allocator.h: New file.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@67777 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
30 files changed, 2190 insertions, 1532 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0c01a43308e..ad3c2d65ab9 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,46 @@ +2003-06-11 Benjamin Kosnik <bkoz@redhat.com> + + * include/bits/stl_alloc.h (__debug_alloc): Move out. + (__malloc_alloc): Same. + (__pool_alloc): Same. + (__new_alloc): Same. + Rename to.. + * include/bits/allocator.h: ...this. + * include/bits/stl_deque.h: Modify comment. + * include/bits/stl_tree.h: Modify include. + * include/std/std_memory.h: Same. + * include/ext/rope: Same. + * include/ext/slist: Same. + * include/std/std_vector.h: Same. + * include/std/std_stack.h: Same. + * include/std/std_queue.h: Same. + * include/std/std_list.h: Same. + * include/std/std_deque.h: Same. + * include/backward/alloc.h: Same. + * include/ext/debug_allocator.h: New. + * include/ext/malloc_allocator.h: New. + * include/ext/pool_allocator.h: New. + * include/ext/new_allocator.h: New. + * include/bits/pthread_allocimpl.h: Remove. + * include/bits/stl_pthread_alloc.h: Remove. + * include/Makefile.am (ext_headers): Add. + * include/Makefile.in: Regenerate. + * src/stl-inst.cc: Use __gnu_cxx namespace. + * src/stl-inst.cc: Move to... + * src/allocator-inst.cc: Here. + * src/Makefile.am (sources): Update. + * src/Makefile.in: Regenerate. + * config/linker-map.gnu: Remove __pool_alloc bits. + * testsuite/ext/headers.cc: Add. + * testsuite/ext/allocators.cc: Fixup. + +2003-06-11 Stefan Olsson <stefan@snon.net> + Ola Rönnerup <fnolis@home.se> + + * include/Makefile.am (ext_headers): Add. + * include/Makefile.in: Regenerate. + * include/ext/mt_allocator.h: New file. + 2003-06-10 Paolo Carlini <pcarlini@unitus.it> * include/bits/fstream.tcc (close): Clean up a bit. diff --git a/libstdc++-v3/config/linker-map.gnu b/libstdc++-v3/config/linker-map.gnu index 6f87a0b9967..6723a057e07 100644 --- a/libstdc++-v3/config/linker-map.gnu +++ b/libstdc++-v3/config/linker-map.gnu @@ -78,15 +78,6 @@ GLIBCPP_3.4 { # bool has_facet _ZSt9has_facet*; - # std::__pool_alloc - _ZNSt12__pool_allocILb1ELi0EE10deallocateEPv[jm]*; - _ZNSt12__pool_allocILb1ELi0EE8allocateE[jm]*; - _ZNSt12__pool_allocILb1ELi0EE5_Lock*; - _ZNSt12__pool_allocILb1ELi0EE12_S_force_newE; - _ZNSt12__pool_allocILb1ELi0EE12_S_free_listE; - _ZNSt12__pool_allocILb1ELi0EE7_S_lockE; - _ZNSt12__pool_allocILb1ELi0EE9_S_refillE[jm]; - # operator new(size_t) _Znw[jm]; # operator new(size_t, std::nothrow_t const&) diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 5c200dcd8a7..760e85ba4e8 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -103,6 +103,8 @@ std_headers_rename = \ bits_srcdir = ${glibcpp_srcdir}/include/bits bits_builddir = ./bits bits_headers = \ + ${bits_srcdir}/allocator.h \ + ${bits_srcdir}/allocator_traits.h \ ${bits_srcdir}/basic_ios.h \ ${bits_srcdir}/basic_ios.tcc \ ${bits_srcdir}/basic_string.h \ @@ -129,14 +131,12 @@ bits_headers = \ ${bits_srcdir}/localefwd.h \ ${bits_srcdir}/mask_array.h \ ${bits_srcdir}/ostream.tcc \ - ${bits_srcdir}/pthread_allocimpl.h \ ${bits_srcdir}/stream_iterator.h \ ${bits_srcdir}/streambuf_iterator.h \ ${bits_srcdir}/slice_array.h \ ${bits_srcdir}/sstream.tcc \ ${bits_srcdir}/stl_algo.h \ ${bits_srcdir}/stl_algobase.h \ - ${bits_srcdir}/stl_alloc.h \ ${bits_srcdir}/stl_bvector.h \ ${bits_srcdir}/stl_construct.h \ ${bits_srcdir}/stl_deque.h \ @@ -151,7 +151,6 @@ bits_headers = \ ${bits_srcdir}/stl_multiset.h \ ${bits_srcdir}/stl_numeric.h \ ${bits_srcdir}/stl_pair.h \ - ${bits_srcdir}/stl_pthread_alloc.h \ ${bits_srcdir}/stl_queue.h \ ${bits_srcdir}/stl_raw_storage_iter.h \ ${bits_srcdir}/stl_relops.h \ @@ -215,6 +214,7 @@ ext_srcdir = ${glibcpp_srcdir}/include/ext ext_builddir = ./ext ext_headers = \ ${ext_srcdir}/algorithm \ + ${ext_srcdir}/debug_allocator.h \ ${ext_srcdir}/enc_filebuf.h \ ${ext_srcdir}/stdio_filebuf.h \ ${ext_srcdir}/stdio_sync_filebuf.h \ @@ -222,8 +222,12 @@ ext_headers = \ ${ext_srcdir}/hash_map \ ${ext_srcdir}/hash_set \ ${ext_srcdir}/iterator \ + ${ext_srcdir}/malloc_allocator.h \ ${ext_srcdir}/memory \ + ${ext_srcdir}/mt_allocator.h \ + ${ext_srcdir}/new_allocator.h \ ${ext_srcdir}/numeric \ + ${ext_srcdir}/pool_allocator.h \ ${ext_srcdir}/rb_tree \ ${ext_srcdir}/rope \ ${ext_srcdir}/ropeimpl.h \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 7dfd79311e1..33d5a81846c 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -222,6 +222,8 @@ std_headers_rename = \ bits_srcdir = ${glibcpp_srcdir}/include/bits bits_builddir = ./bits bits_headers = \ + ${bits_srcdir}/allocator.h \ + ${bits_srcdir}/allocator_traits.h \ ${bits_srcdir}/basic_ios.h \ ${bits_srcdir}/basic_ios.tcc \ ${bits_srcdir}/basic_string.h \ @@ -248,14 +250,12 @@ bits_headers = \ ${bits_srcdir}/localefwd.h \ ${bits_srcdir}/mask_array.h \ ${bits_srcdir}/ostream.tcc \ - ${bits_srcdir}/pthread_allocimpl.h \ ${bits_srcdir}/stream_iterator.h \ ${bits_srcdir}/streambuf_iterator.h \ ${bits_srcdir}/slice_array.h \ ${bits_srcdir}/sstream.tcc \ ${bits_srcdir}/stl_algo.h \ ${bits_srcdir}/stl_algobase.h \ - ${bits_srcdir}/stl_alloc.h \ ${bits_srcdir}/stl_bvector.h \ ${bits_srcdir}/stl_construct.h \ ${bits_srcdir}/stl_deque.h \ @@ -270,7 +270,6 @@ bits_headers = \ ${bits_srcdir}/stl_multiset.h \ ${bits_srcdir}/stl_numeric.h \ ${bits_srcdir}/stl_pair.h \ - ${bits_srcdir}/stl_pthread_alloc.h \ ${bits_srcdir}/stl_queue.h \ ${bits_srcdir}/stl_raw_storage_iter.h \ ${bits_srcdir}/stl_relops.h \ @@ -336,6 +335,7 @@ ext_srcdir = ${glibcpp_srcdir}/include/ext ext_builddir = ./ext ext_headers = \ ${ext_srcdir}/algorithm \ + ${ext_srcdir}/debug_allocator.h \ ${ext_srcdir}/enc_filebuf.h \ ${ext_srcdir}/stdio_filebuf.h \ ${ext_srcdir}/stdio_sync_filebuf.h \ @@ -343,8 +343,12 @@ ext_headers = \ ${ext_srcdir}/hash_map \ ${ext_srcdir}/hash_set \ ${ext_srcdir}/iterator \ + ${ext_srcdir}/malloc_allocator.h \ ${ext_srcdir}/memory \ + ${ext_srcdir}/mt_allocator.h \ + ${ext_srcdir}/new_allocator.h \ ${ext_srcdir}/numeric \ + ${ext_srcdir}/pool_allocator.h \ ${ext_srcdir}/rb_tree \ ${ext_srcdir}/rope \ ${ext_srcdir}/ropeimpl.h \ diff --git a/libstdc++-v3/include/backward/alloc.h b/libstdc++-v3/include/backward/alloc.h index 6bcc421b7af..b748ef26c01 100644 --- a/libstdc++-v3/include/backward/alloc.h +++ b/libstdc++-v3/include/backward/alloc.h @@ -45,15 +45,15 @@ #include "backward_warning.h" #include <bits/c++config.h> -#include <bits/stl_alloc.h> +#include <bits/allocator.h> +#include <ext/debug_allocator.h> +#include <ext/malloc_allocator.h> -using std::__malloc_alloc; -using std::__simple_alloc; -using std::__debug_alloc; +using __gnu_cxx::__malloc_alloc; +using __gnu_cxx::__debug_alloc; +using __gnu_cxx::__pool_alloc; using std::__alloc; -using std::__single_client_alloc; -using std::__pool_alloc; +using std::__simple_alloc; using std::allocator; - #endif diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h new file mode 100644 index 00000000000..b6dec02572a --- /dev/null +++ b/libstdc++-v3/include/bits/allocator.h @@ -0,0 +1,215 @@ +// Allocators -*- C++ -*- + +// Copyright (C) 2001, 2002, 2003 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) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 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. + +/* + * 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 allocator.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +/** + * @defgroup Allocators Memory Allocators + * @if maint + * allocator.h implements some node allocators. These are NOT the same as + * allocators in the C++ standard, nor in the original H-P STL. They do not + * encapsulate different pointer types; we assume that there is only one + * pointer type. The C++ standard allocators are intended to allocate + * individual objects, not pools or arenas. + * + * In this file allocators are of two different styles: "standard" and + * "SGI" (quotes included). "Standard" allocators conform to 20.4. "SGI" + * allocators differ in AT LEAST the following ways (add to this list as you + * discover them): + * + * - "Standard" allocate() takes two parameters (n_count,hint=0) but "SGI" + * allocate() takes one paramter (n_size). + * - Likewise, "standard" deallocate()'s argument is a count, but in "SGI" + * is a byte size. + * - max_size(), construct(), and destroy() are missing in "SGI" allocators. + * - reallocate(p,oldsz,newsz) is added in "SGI", and behaves as + * if p=realloc(p,newsz). + * + * "SGI" allocators may be wrapped in __allocator to convert the interface + * into a "standard" one. + * @endif + * + * The canonical description of these classes is in docs/html/ext/howto.html + * or online at http://gcc.gnu.org/onlinedocs/libstdc++/ext/howto.html#3 +*/ + +#ifndef _ALLOCATOR_H +#define _ALLOCATOR_H 1 + +#include <bits/functexcept.h> // For __throw_bad_alloc +#include <bits/allocator_traits.h> + +// Pick a default underlying allocator. +#include <ext/pool_allocator.h> + +namespace std +{ + typedef __gnu_cxx::__pool_alloc<true, 0> __alloc; + + /// The version for the default allocator. + template<typename _Tp, typename _Tp1> + struct _Alloc_traits<_Tp, allocator<_Tp1> > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __alloc> _Alloc_type; + typedef allocator<_Tp> allocator_type; + }; + //@} +} + +namespace std +{ + /** + * @brief The "standard" allocator, as per [20.4]. + * + * The private _Alloc is "SGI" style. (See comments at the top + * of allocator.h.) + * + * The underlying allocator behaves as follows. + * - __pool_alloc is used via two typedefs + * - "__alloc" typedef is threadsafe via the locks + * - __new_alloc is used for memory requests + * + * (See @link Allocators allocators info @endlink for more.) + */ + template<typename _Tp> + class allocator + { + // The underlying allocator. + typedef __alloc _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 allocator<_Tp1> other; }; + + allocator() throw() { } + + allocator(const allocator&) throw() { } + + template<typename _Tp1> + allocator(const allocator<_Tp1>&) throw() { } + + ~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. + _Tp* + allocate(size_type __n, const void* = 0) + { + _Tp* __ret = 0; + if (__n) + { + if (__n <= this->max_size()) + __ret = static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))); + else + __throw_bad_alloc(); + } + return __ret; + } + + // __p is not permitted to be a null pointer. + void + deallocate(pointer __p, size_type __n) + { _Alloc::deallocate(__p, __n * sizeof(_Tp)); } + + size_type + max_size() const throw() { return size_t(-1) / sizeof(_Tp); } + + void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } + + void destroy(pointer __p) { __p->~_Tp(); } + }; + + template<> + class allocator<void> + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + template<typename _Tp1> + struct rebind + { typedef allocator<_Tp1> other; }; + }; + + + template<typename _T1, typename _T2> + inline bool + operator==(const allocator<_T1>&, const allocator<_T2>&) + { return true; } + + template<typename _T1, typename _T2> + inline bool + operator!=(const allocator<_T1>&, const allocator<_T2>&) + { return false; } + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. +#if _GLIBCPP_EXTERN_TEMPLATE + extern template class allocator<char>; + extern template class allocator<wchar_t>; +#endif +} // namespace std + +#endif diff --git a/libstdc++-v3/include/bits/allocator_traits.h b/libstdc++-v3/include/bits/allocator_traits.h new file mode 100644 index 00000000000..be9a352fdd9 --- /dev/null +++ b/libstdc++-v3/include/bits/allocator_traits.h @@ -0,0 +1,236 @@ +// Allocators -*- C++ -*- + +// Copyright (C) 2001, 2002, 2003 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) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 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. + +/* + * 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. + */ + +#ifndef _ALLOCATOR_TRAITS_H +#define _ALLOCATOR_TRAITS_H 1 + +#include <cstddef> + +namespace std +{ + /** + * @if maint + * This is used primarily (only?) in _Alloc_traits and other places to + * help provide the _Alloc_type typedef. All it does is forward the + * requests after some minimal checking. + * + * This is neither "standard"-conforming nor "SGI". The _Alloc parameter + * must be "SGI" style. + * @endif + * (See @link Allocators allocators info @endlink for more.) + */ + template<typename _Tp, typename _Alloc> + class __simple_alloc + { + public: + static _Tp* + allocate(size_t __n) + { + _Tp* __ret = 0; + if (__n) + __ret = static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))); + return __ret; + } + + static _Tp* + allocate() + { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); } + + static void + deallocate(_Tp* __p, size_t __n) + { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); } + + static void + deallocate(_Tp* __p) + { _Alloc::deallocate(__p, sizeof (_Tp)); } + }; + + + /** + * @if maint + * Allocator adaptor to turn an "SGI" style allocator (e.g., + * __alloc, __malloc_alloc) into a "standard" conforming + * allocator. Note that this adaptor does *not* assume that all + * objects of the underlying alloc class are identical, nor does it + * assume that all of the underlying alloc's member functions are + * static member functions. Note, also, that __allocator<_Tp, + * __alloc> is essentially the same thing as allocator<_Tp>. + * @endif + * (See @link Allocators allocators info @endlink for more.) + */ + template<typename _Tp, typename _Alloc> + struct __allocator + { + _Alloc __underlying_alloc; + + 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 __allocator<_Tp1, _Alloc> other; }; + + __allocator() throw() { } + + __allocator(const __allocator& __a) throw() + : __underlying_alloc(__a.__underlying_alloc) { } + + template<typename _Tp1> + __allocator(const __allocator<_Tp1, _Alloc>& __a) throw() + : __underlying_alloc(__a.__underlying_alloc) { } + + ~__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. + _Tp* + allocate(size_type __n, const void* = 0) + { + _Tp* __ret = 0; + if (__n) + __ret = static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))); + return __ret; + } + + // __p is not permitted to be a null pointer. + void + deallocate(pointer __p, size_type __n) + { __underlying_alloc.deallocate(__p, __n * sizeof(_Tp)); } + + size_type + max_size() const throw() { return size_t(-1) / sizeof(_Tp); } + + void + construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } + + void + destroy(pointer __p) { __p->~_Tp(); } + }; + + template<typename _Alloc> + struct __allocator<void, _Alloc> + { + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + template<typename _Tp1> + struct rebind + { typedef __allocator<_Tp1, _Alloc> other; }; + }; + + template<typename _Tp, typename _Alloc> + inline bool + operator==(const __allocator<_Tp,_Alloc>& __a1, + const __allocator<_Tp,_Alloc>& __a2) + { return __a1.__underlying_alloc == __a2.__underlying_alloc; } + + template<typename _Tp, typename _Alloc> + inline bool + operator!=(const __allocator<_Tp, _Alloc>& __a1, + const __allocator<_Tp, _Alloc>& __a2) + { return __a1.__underlying_alloc != __a2.__underlying_alloc; } + + + /** + * @if maint + * Another allocator adaptor: _Alloc_traits. This serves two purposes. + * First, make it possible to write containers that can use either "SGI" + * style allocators or "standard" allocators. Second, provide a mechanism + * so that containers can query whether or not the allocator has distinct + * instances. If not, the container can avoid wasting a word of memory to + * store an empty object. For examples of use, see stl_vector.h, etc, or + * any of the other classes derived from this one. + * + * This adaptor uses partial specialization. The general case of + * _Alloc_traits<_Tp, _Alloc> assumes that _Alloc is a + * standard-conforming allocator, possibly with non-equal instances and + * non-static members. (It still behaves correctly even if _Alloc has + * static member and if all instances are equal. Refinements affect + * performance, not correctness.) + * + * There are always two members: allocator_type, which is a standard- + * conforming allocator type for allocating objects of type _Tp, and + * _S_instanceless, a static const member of type bool. If + * _S_instanceless is true, this means that there is no difference + * between any two instances of type allocator_type. Furthermore, if + * _S_instanceless is true, then _Alloc_traits has one additional + * member: _Alloc_type. This type encapsulates allocation and + * deallocation of objects of type _Tp through a static interface; it + * has two member functions, whose signatures are + * + * - static _Tp* allocate(size_t) + * - static void deallocate(_Tp*, size_t) + * + * The size_t parameters are "standard" style (see top of + * allocator.h) in that they take counts, not sizes. + * + * @endif + * (See @link Allocators allocators info @endlink for more.) + */ + //@{ + // The fully general version. + template<typename _Tp, typename _Allocator> + struct _Alloc_traits + { + static const bool _S_instanceless = false; + typedef typename _Allocator::template rebind<_Tp>::other allocator_type; + }; + + template<typename _Tp, typename _Allocator> + const bool _Alloc_traits<_Tp, _Allocator>::_S_instanceless; +} // namespace std + +#endif diff --git a/libstdc++-v3/include/bits/pthread_allocimpl.h b/libstdc++-v3/include/bits/pthread_allocimpl.h deleted file mode 100644 index 050b2060fc4..00000000000 --- a/libstdc++-v3/include/bits/pthread_allocimpl.h +++ /dev/null @@ -1,525 +0,0 @@ -// POSIX thread-related memory allocation -*- C++ -*- - -// Copyright (C) 2001 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) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, -// USA. - -// 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. - -/* - * Copyright (c) 1996 - * 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 pthread_allocimpl.h - * This is an internal header file, included by other library headers. - * You should not attempt to use it directly. - */ - -#ifndef _CPP_BITS_PTHREAD_ALLOCIMPL_H -#define _CPP_BITS_PTHREAD_ALLOCIMPL_H 1 - -// Pthread-specific node allocator. -// This is similar to the default allocator, except that free-list -// information is kept separately for each thread, avoiding locking. -// This should be reasonably fast even in the presence of threads. -// The down side is that storage may not be well-utilized. -// It is not an error to allocate memory in thread A and deallocate -// it in thread B. But this effectively transfers ownership of the memory, -// so that it can only be reallocated by thread B. Thus this can effectively -// result in a storage leak if it's done on a regular basis. -// It can also result in frequent sharing of -// cache lines among processors, with potentially serious performance -// consequences. - -#include <bits/c++config.h> -#include <cerrno> -#include <bits/stl_alloc.h> -#ifndef __RESTRICT -# define __RESTRICT -#endif - -#include <new> - -namespace std -{ - -#define __STL_DATA_ALIGNMENT 8 - -union _Pthread_alloc_obj { - union _Pthread_alloc_obj * __free_list_link; - char __client_data[__STL_DATA_ALIGNMENT]; /* The client sees this. */ -}; - -// Pthread allocators don't appear to the client to have meaningful -// instances. We do in fact need to associate some state with each -// thread. That state is represented by -// _Pthread_alloc_per_thread_state<_Max_size>. - -template<size_t _Max_size> -struct _Pthread_alloc_per_thread_state { - typedef _Pthread_alloc_obj __obj; - enum { _S_NFREELISTS = _Max_size/__STL_DATA_ALIGNMENT }; - _Pthread_alloc_obj* volatile __free_list[_S_NFREELISTS]; - _Pthread_alloc_per_thread_state<_Max_size> * __next; - // Free list link for list of available per thread structures. - // When one of these becomes available for reuse due to thread - // termination, any objects in its free list remain associated - // with it. The whole structure may then be used by a newly - // created thread. - _Pthread_alloc_per_thread_state() : __next(0) - { - memset((void *)__free_list, 0, (size_t) _S_NFREELISTS * sizeof(__obj *)); - } - // Returns an object of size __n, and possibly adds to size n free list. - void *_M_refill(size_t __n); -}; - -// Pthread-specific allocator. -// The argument specifies the largest object size allocated from per-thread -// free lists. Larger objects are allocated using malloc_alloc. -// Max_size must be a power of 2. -template <size_t _Max_size = 128> -class _Pthread_alloc_template { - -public: // but only for internal use: - - typedef _Pthread_alloc_obj __obj; - - // Allocates a chunk for nobjs of size size. nobjs may be reduced - // if it is inconvenient to allocate the requested number. - static char *_S_chunk_alloc(size_t __size, int &__nobjs); - - enum {_S_ALIGN = __STL_DATA_ALIGNMENT}; - - static size_t _S_round_up(size_t __bytes) { - return (((__bytes) + (int) _S_ALIGN-1) & ~((int) _S_ALIGN - 1)); - } - static size_t _S_freelist_index(size_t __bytes) { - return (((__bytes) + (int) _S_ALIGN-1)/(int)_S_ALIGN - 1); - } - -private: - // Chunk allocation state. And other shared state. - // Protected by _S_chunk_allocator_lock. - static pthread_mutex_t _S_chunk_allocator_lock; - static char *_S_start_free; - static char *_S_end_free; - static size_t _S_heap_size; - static _Pthread_alloc_per_thread_state<_Max_size>* _S_free_per_thread_states; - static pthread_key_t _S_key; - static bool _S_key_initialized; - // Pthread key under which per thread state is stored. - // Allocator instances that are currently unclaimed by any thread. - static void _S_destructor(void *instance); - // Function to be called on thread exit to reclaim per thread - // state. - static _Pthread_alloc_per_thread_state<_Max_size> *_S_new_per_thread_state(); - // Return a recycled or new per thread state. - static _Pthread_alloc_per_thread_state<_Max_size> *_S_get_per_thread_state(); - // ensure that the current thread has an associated - // per thread state. - class _M_lock; - friend class _M_lock; - class _M_lock { - public: - _M_lock () { pthread_mutex_lock(&_S_chunk_allocator_lock); } - ~_M_lock () { pthread_mutex_unlock(&_S_chunk_allocator_lock); } - }; - -public: - - /* n must be > 0 */ - static void * allocate(size_t __n) - { - __obj * volatile * __my_free_list; - __obj * __RESTRICT __result; - _Pthread_alloc_per_thread_state<_Max_size>* __a; - - if (__n > _Max_size) { - return(malloc_alloc::allocate(__n)); - } - if (!_S_key_initialized || - !(__a = (_Pthread_alloc_per_thread_state<_Max_size>*) - pthread_getspecific(_S_key))) { - __a = _S_get_per_thread_state(); - } - __my_free_list = __a -> __free_list + _S_freelist_index(__n); - __result = *__my_free_list; - if (__result == 0) { - void *__r = __a -> _M_refill(_S_round_up(__n)); - return __r; - } - *__my_free_list = __result -> __free_list_link; - return (__result); - }; - - /* p may not be 0 */ - static void deallocate(void *__p, size_t __n) - { - __obj *__q = (__obj *)__p; - __obj * volatile * __my_free_list; - _Pthread_alloc_per_thread_state<_Max_size>* __a; - - if (__n > _Max_size) { - malloc_alloc::deallocate(__p, __n); - return; - } - if (!_S_key_initialized || - !(__a = (_Pthread_alloc_per_thread_state<_Max_size> *) - pthread_getspecific(_S_key))) { - __a = _S_get_per_thread_state(); - } - __my_free_list = __a->__free_list + _S_freelist_index(__n); - __q -> __free_list_link = *__my_free_list; - *__my_free_list = __q; - } - - static void * reallocate(void *__p, size_t __old_sz, size_t __new_sz); - -} ; - -typedef _Pthread_alloc_template<> pthread_alloc; - - -template <size_t _Max_size> -void _Pthread_alloc_template<_Max_size>::_S_destructor(void * __instance) -{ - _M_lock __lock_instance; // Need to acquire lock here. - _Pthread_alloc_per_thread_state<_Max_size>* __s = - (_Pthread_alloc_per_thread_state<_Max_size> *)__instance; - __s -> __next = _S_free_per_thread_states; - _S_free_per_thread_states = __s; -} - -template <size_t _Max_size> -_Pthread_alloc_per_thread_state<_Max_size> * -_Pthread_alloc_template<_Max_size>::_S_new_per_thread_state() -{ - /* lock already held here. */ - if (0 != _S_free_per_thread_states) { - _Pthread_alloc_per_thread_state<_Max_size> *__result = - _S_free_per_thread_states; - _S_free_per_thread_states = _S_free_per_thread_states -> __next; - return __result; - } else { - return new _Pthread_alloc_per_thread_state<_Max_size>; - } -} - -template <size_t _Max_size> -_Pthread_alloc_per_thread_state<_Max_size> * -_Pthread_alloc_template<_Max_size>::_S_get_per_thread_state() -{ - /*REFERENCED*/ - _M_lock __lock_instance; // Need to acquire lock here. - int __ret_code; - _Pthread_alloc_per_thread_state<_Max_size> * __result; - if (!_S_key_initialized) { - if (pthread_key_create(&_S_key, _S_destructor)) { - std::__throw_bad_alloc(); // defined in funcexcept.h - } - _S_key_initialized = true; - } - __result = _S_new_per_thread_state(); - __ret_code = pthread_setspecific(_S_key, __result); - if (__ret_code) { - if (__ret_code == ENOMEM) { - std::__throw_bad_alloc(); - } else { - // EINVAL - abort(); - } - } - return __result; -} - -/* We allocate memory in large chunks in order to avoid fragmenting */ -/* the malloc heap too much. */ -/* We assume that size is properly aligned. */ -template <size_t _Max_size> -char *_Pthread_alloc_template<_Max_size> -::_S_chunk_alloc(size_t __size, int &__nobjs) -{ - { - char * __result; - size_t __total_bytes; - size_t __bytes_left; - /*REFERENCED*/ - _M_lock __lock_instance; // Acquire lock for this routine - - __total_bytes = __size * __nobjs; - __bytes_left = _S_end_free - _S_start_free; - if (__bytes_left >= __total_bytes) { - __result = _S_start_free; - _S_start_free += __total_bytes; - return(__result); - } else if (__bytes_left >= __size) { - __nobjs = __bytes_left/__size; - __total_bytes = __size * __nobjs; - __result = _S_start_free; - _S_start_free += __total_bytes; - return(__result); - } else { - size_t __bytes_to_get = - 2 * __total_bytes + _S_round_up(_S_heap_size >> 4); - // Try to make use of the left-over piece. - if (__bytes_left > 0) { - _Pthread_alloc_per_thread_state<_Max_size>* __a = - (_Pthread_alloc_per_thread_state<_Max_size>*) - pthread_getspecific(_S_key); - __obj * volatile * __my_free_list = - __a->__free_list + _S_freelist_index(__bytes_left); - - ((__obj *)_S_start_free) -> __free_list_link = *__my_free_list; - *__my_free_list = (__obj *)_S_start_free; - } -# ifdef _SGI_SOURCE - // Try to get memory that's aligned on something like a - // cache line boundary, so as to avoid parceling out - // parts of the same line to different threads and thus - // possibly different processors. - { - const int __cache_line_size = 128; // probable upper bound - __bytes_to_get &= ~(__cache_line_size-1); - _S_start_free = (char *)memalign(__cache_line_size, __bytes_to_get); - if (0 == _S_start_free) { - _S_start_free = (char *)malloc_alloc::allocate(__bytes_to_get); - } - } -# else /* !SGI_SOURCE */ - _S_start_free = (char *)malloc_alloc::allocate(__bytes_to_get); -# endif - _S_heap_size += __bytes_to_get; - _S_end_free = _S_start_free + __bytes_to_get; - } - } - // lock is released here - return(_S_chunk_alloc(__size, __nobjs)); -} - - -/* Returns an object of size n, and optionally adds to size n free list.*/ -/* We assume that n is properly aligned. */ -/* We hold the allocation lock. */ -template <size_t _Max_size> -void *_Pthread_alloc_per_thread_state<_Max_size> -::_M_refill(size_t __n) -{ - int __nobjs = 128; - char * __chunk = - _Pthread_alloc_template<_Max_size>::_S_chunk_alloc(__n, __nobjs); - __obj * volatile * __my_free_list; - __obj * __result; - __obj * __current_obj, * __next_obj; - int __i; - - if (1 == __nobjs) { - return(__chunk); - } - __my_free_list = __free_list - + _Pthread_alloc_template<_Max_size>::_S_freelist_index(__n); - - /* Build free list in chunk */ - __result = (__obj *)__chunk; - *__my_free_list = __next_obj = (__obj *)(__chunk + __n); - for (__i = 1; ; __i++) { - __current_obj = __next_obj; - __next_obj = (__obj *)((char *)__next_obj + __n); - if (__nobjs - 1 == __i) { - __current_obj -> __free_list_link = 0; - break; - } else { - __current_obj -> __free_list_link = __next_obj; - } - } - return(__result); -} - -template <size_t _Max_size> -void *_Pthread_alloc_template<_Max_size> -::reallocate(void *__p, size_t __old_sz, size_t __new_sz) -{ - void * __result; - size_t __copy_sz; - - if (__old_sz > _Max_size - && __new_sz > _Max_size) { - return(realloc(__p, __new_sz)); - } - if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return(__p); - __result = allocate(__new_sz); - __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz; - memcpy(__result, __p, __copy_sz); - deallocate(__p, __old_sz); - return(__result); -} - -template <size_t _Max_size> -_Pthread_alloc_per_thread_state<_Max_size> * -_Pthread_alloc_template<_Max_size>::_S_free_per_thread_states = 0; - -template <size_t _Max_size> -pthread_key_t _Pthread_alloc_template<_Max_size>::_S_key; - -template <size_t _Max_size> -bool _Pthread_alloc_template<_Max_size>::_S_key_initialized = false; - -template <size_t _Max_size> -pthread_mutex_t _Pthread_alloc_template<_Max_size>::_S_chunk_allocator_lock -= PTHREAD_MUTEX_INITIALIZER; - -template <size_t _Max_size> -char *_Pthread_alloc_template<_Max_size> -::_S_start_free = 0; - -template <size_t _Max_size> -char *_Pthread_alloc_template<_Max_size> -::_S_end_free = 0; - -template <size_t _Max_size> -size_t _Pthread_alloc_template<_Max_size> -::_S_heap_size = 0; - - -template <class _Tp> -class pthread_allocator { - typedef pthread_alloc _S_Alloc; // The underlying 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 <class _NewType> struct rebind { - typedef pthread_allocator<_NewType> other; - }; - - pthread_allocator() throw() {} - pthread_allocator(const pthread_allocator& a) throw() {} - template <class _OtherType> - pthread_allocator(const pthread_allocator<_OtherType>&) - throw() {} - ~pthread_allocator() throw() {} - - pointer address(reference __x) const { return &__x; } - const_pointer address(const_reference __x) const { return &__x; } - - // __n is permitted to be 0. The C++ standard says nothing about what - // the return value is when __n == 0. - _Tp* allocate(size_type __n, const void* = 0) { - return __n != 0 ? static_cast<_Tp*>(_S_Alloc::allocate(__n * sizeof(_Tp))) - : 0; - } - - // p is not permitted to be a null pointer. - void deallocate(pointer __p, size_type __n) - { _S_Alloc::deallocate(__p, __n * sizeof(_Tp)); } - - size_type max_size() const throw() - { return size_t(-1) / sizeof(_Tp); } - - void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } - void destroy(pointer _p) { _p->~_Tp(); } -}; - -template<> -class pthread_allocator<void> { -public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef void* pointer; - typedef const void* const_pointer; - typedef void value_type; - - template <class _NewType> struct rebind { - typedef pthread_allocator<_NewType> other; - }; -}; - -template <size_t _Max_size> -inline bool operator==(const _Pthread_alloc_template<_Max_size>&, - const _Pthread_alloc_template<_Max_size>&) -{ - return true; -} - -template <class _T1, class _T2> -inline bool operator==(const pthread_allocator<_T1>&, - const pthread_allocator<_T2>& a2) -{ - return true; -} - -template <class _T1, class _T2> -inline bool operator!=(const pthread_allocator<_T1>&, - const pthread_allocator<_T2>&) -{ - return false; -} - -template <class _Tp, size_t _Max_size> -struct _Alloc_traits<_Tp, _Pthread_alloc_template<_Max_size> > -{ - static const bool _S_instanceless = true; - typedef simple_alloc<_Tp, _Pthread_alloc_template<_Max_size> > _Alloc_type; - typedef __allocator<_Tp, _Pthread_alloc_template<_Max_size> > - allocator_type; -}; - -template <class _Tp, class _Atype, size_t _Max> -struct _Alloc_traits<_Tp, __allocator<_Atype, _Pthread_alloc_template<_Max> > > -{ - static const bool _S_instanceless = true; - typedef simple_alloc<_Tp, _Pthread_alloc_template<_Max> > _Alloc_type; - typedef __allocator<_Tp, _Pthread_alloc_template<_Max> > allocator_type; -}; - -template <class _Tp, class _Atype> -struct _Alloc_traits<_Tp, pthread_allocator<_Atype> > -{ - static const bool _S_instanceless = true; - typedef simple_alloc<_Tp, _Pthread_alloc_template<> > _Alloc_type; - typedef pthread_allocator<_Tp> allocator_type; -}; - - -} // namespace std - -#endif /* _CPP_BITS_PTHREAD_ALLOCIMPL_H */ - -// Local Variables: -// mode:C++ -// End: diff --git a/libstdc++-v3/include/bits/stl_alloc.h b/libstdc++-v3/include/bits/stl_alloc.h deleted file mode 100644 index 3d26d6d645d..00000000000 --- a/libstdc++-v3/include/bits/stl_alloc.h +++ /dev/null @@ -1,900 +0,0 @@ -// Allocators -*- C++ -*- - -// Copyright (C) 2001, 2002, 2003 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) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, -// USA. - -// 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. - -/* - * 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 stl_alloc.h - * This is an internal header file, included by other library headers. - * You should not attempt to use it directly. - */ - -#ifndef __GLIBCPP_INTERNAL_ALLOC_H -#define __GLIBCPP_INTERNAL_ALLOC_H - -/** - * @defgroup Allocators Memory Allocators - * @if maint - * stl_alloc.h implements some node allocators. These are NOT the same as - * allocators in the C++ standard, nor in the original H-P STL. They do not - * encapsulate different pointer types; we assume that there is only one - * pointer type. The C++ standard allocators are intended to allocate - * individual objects, not pools or arenas. - * - * In this file allocators are of two different styles: "standard" and - * "SGI" (quotes included). "Standard" allocators conform to 20.4. "SGI" - * allocators differ in AT LEAST the following ways (add to this list as you - * discover them): - * - * - "Standard" allocate() takes two parameters (n_count,hint=0) but "SGI" - * allocate() takes one paramter (n_size). - * - Likewise, "standard" deallocate()'s argument is a count, but in "SGI" - * is a byte size. - * - max_size(), construct(), and destroy() are missing in "SGI" allocators. - * - reallocate(p,oldsz,newsz) is added in "SGI", and behaves as - * if p=realloc(p,newsz). - * - * "SGI" allocators may be wrapped in __allocator to convert the interface - * into a "standard" one. - * @endif - * - * The canonical description of these classes is in docs/html/ext/howto.html - * or online at http://gcc.gnu.org/onlinedocs/libstdc++/ext/howto.html#3 -*/ - -#include <cstddef> -#include <cstdlib> -#include <cstring> -#include <bits/functexcept.h> // For __throw_bad_alloc -#include <bits/stl_threads.h> -#include <bits/atomicity.h> - -namespace std -{ - /** - * @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 - * (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); } - }; - - - /** - * @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 - * (See @link Allocators allocators info @endlink for more.) - */ - template<int __inst> - class __malloc_alloc - { - 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; - } - }; - - // malloc_alloc out-of-memory handling - template<int __inst> - void (* __malloc_alloc<__inst>::__malloc_alloc_oom_handler)() = 0; - - 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; - } - } - - - /** - * @if maint - * This is used primarily (only?) in _Alloc_traits and other places to - * help provide the _Alloc_type typedef. All it does is forward the - * requests after some minimal checking. - * - * This is neither "standard"-conforming nor "SGI". The _Alloc parameter - * must be "SGI" style. - * @endif - * (See @link Allocators allocators info @endlink for more.) - */ - template<typename _Tp, typename _Alloc> - class __simple_alloc - { - public: - static _Tp* - allocate(size_t __n) - { - _Tp* __ret = 0; - if (__n) - __ret = static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))); - return __ret; - } - - static _Tp* - allocate() - { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); } - - static void - deallocate(_Tp* __p, size_t __n) - { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); } - - static void - deallocate(_Tp* __p) - { _Alloc::deallocate(__p, sizeof (_Tp)); } - }; - - - /** - * @if maint - * An adaptor for an underlying allocator (_Alloc) to check the size - * arguments for debugging. - * - * "There is some evidence that this can confuse Purify." - SGI comment - * - * 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 - { - private: - // Size of space used to store size. Note that this must be - // large enough to preserve alignment. - enum {_S_extra = 8}; - - public: - static void* - allocate(size_t __n) - { - char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra); - *(size_t*)__result = __n; - return __result + (int) _S_extra; - } - - static void - deallocate(void* __p, size_t __n) - { - char* __real_p = (char*)__p - (int) _S_extra; - if (*(size_t*)__real_p != __n) - abort(); - _Alloc::deallocate(__real_p, __n + (int) _S_extra); - } - }; - - - /** - * @if maint - * Default node allocator. "SGI" style. Uses various allocators to - * fulfill underlying requests (and makes as few requests as possible - * when in default high-speed pool mode). - * - * Important implementation properties: - * 0. If globally mandated, then allocate objects from __new_alloc - * 1. If the clients request an object of size > _S_max_bytes, the resulting - * object will be obtained directly from __new_alloc - * 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 - * without permanently losing part of the object. - * - * The first template parameter specifies whether more than one thread may - * use this allocator. It is safe to allocate an object from one instance - * of a default_alloc and deallocate it with another one. This effectively - * transfers its ownership to the second one. This may have undesirable - * effects on reference locality. - * - * The second parameter is unused and serves only to allow the creation of - * multiple default_alloc instances. Note that containers built on different - * allocator instances have different types, limiting the utility of this - * approach. If you do not wish to share the free lists with the main - * default_alloc instance, instantiate this with a non-zero __inst. - * - * @endif - * (See @link Allocators allocators info @endlink for more.) - */ - template<bool __threads, int __inst> - class __pool_alloc - { - private: - enum {_S_align = 8}; - enum {_S_max_bytes = 128}; - enum {_S_freelists = _S_max_bytes / _S_align}; - - union _Obj - { - union _Obj* _M_free_list_link; - char _M_client_data[1]; // The client sees this. - }; - - static _Obj* volatile _S_free_list[_S_freelists]; - - // Chunk allocation state. - static char* _S_start_free; - static char* _S_end_free; - static size_t _S_heap_size; - - static _STL_mutex_lock _S_lock; - static _Atomic_word _S_force_new; - - static size_t - _S_round_up(size_t __bytes) - { return (((__bytes) + (size_t) _S_align-1) & ~((size_t) _S_align - 1)); } - - static size_t - _S_freelist_index(size_t __bytes) - { return (((__bytes) + (size_t)_S_align - 1)/(size_t)_S_align - 1); } - - // Returns an object of size __n, and optionally adds to size __n - // free list. - static void* - _S_refill(size_t __n); - - // Allocates a chunk for nobjs of size size. nobjs may be reduced - // if it is inconvenient to allocate the requested number. - static char* - _S_chunk_alloc(size_t __size, int& __nobjs); - - // It would be nice to use _STL_auto_lock here. But we need a - // test whether threads are in use. - struct _Lock - { - _Lock() { if (__threads) _S_lock._M_acquire_lock(); } - ~_Lock() { if (__threads) _S_lock._M_release_lock(); } - } __attribute__ ((__unused__)); - friend struct _Lock; - - public: - // __n must be > 0 - static void* - allocate(size_t __n) - { - void* __ret = 0; - - // If there is a race through here, assume answer from getenv - // will resolve in same direction. Inspired by techniques - // to efficiently support threading found in basic_string.h. - if (_S_force_new == 0) - { - if (getenv("GLIBCPP_FORCE_NEW")) - __atomic_add(&_S_force_new, 1); - else - __atomic_add(&_S_force_new, -1); - } - - if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0)) - __ret = __new_alloc::allocate(__n); - else - { - _Obj* volatile* __my_free_list = _S_free_list - + _S_freelist_index(__n); - // Acquire the lock here with a constructor call. This - // ensures that it is released in exit or during stack - // unwinding. - _Lock __lock_instance; - _Obj* __restrict__ __result = *__my_free_list; - if (__builtin_expect(__result == 0, 0)) - __ret = _S_refill(_S_round_up(__n)); - else - { - *__my_free_list = __result -> _M_free_list_link; - __ret = __result; - } - if (__builtin_expect(__ret == 0, 0)) - __throw_bad_alloc(); - } - return __ret; - } - - // __p may not be 0 - static void - deallocate(void* __p, size_t __n) - { - if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0)) - __new_alloc::deallocate(__p, __n); - else - { - _Obj* volatile* __my_free_list = _S_free_list - + _S_freelist_index(__n); - _Obj* __q = (_Obj*)__p; - - // Acquire the lock here with a constructor call. This - // ensures that it is released in exit or during stack - // unwinding. - _Lock __lock_instance; - __q -> _M_free_list_link = *__my_free_list; - *__my_free_list = __q; - } - } - }; - - template<bool __threads, int __inst> _Atomic_word - __pool_alloc<__threads, __inst>::_S_force_new = 0; - - template<bool __threads, int __inst> - inline bool - operator==(const __pool_alloc<__threads,__inst>&, - const __pool_alloc<__threads,__inst>&) - { return true; } - - template<bool __threads, int __inst> - inline bool - operator!=(const __pool_alloc<__threads,__inst>&, - const __pool_alloc<__threads,__inst>&) - { return false; } - - - // We allocate memory in large chunks in order to avoid fragmenting the - // heap too much. We assume that __size is properly aligned. We hold - // the allocation lock. - template<bool __threads, int __inst> - char* - __pool_alloc<__threads, __inst>:: - _S_chunk_alloc(size_t __size, int& __nobjs) - { - char* __result; - size_t __total_bytes = __size * __nobjs; - size_t __bytes_left = _S_end_free - _S_start_free; - - if (__bytes_left >= __total_bytes) - { - __result = _S_start_free; - _S_start_free += __total_bytes; - return __result ; - } - else if (__bytes_left >= __size) - { - __nobjs = (int)(__bytes_left/__size); - __total_bytes = __size * __nobjs; - __result = _S_start_free; - _S_start_free += __total_bytes; - return __result; - } - else - { - size_t __bytes_to_get = - 2 * __total_bytes + _S_round_up(_S_heap_size >> 4); - // Try to make use of the left-over piece. - if (__bytes_left > 0) - { - _Obj* volatile* __my_free_list = - _S_free_list + _S_freelist_index(__bytes_left); - - ((_Obj*)(void*)_S_start_free) -> _M_free_list_link = *__my_free_list; - *__my_free_list = (_Obj*)(void*)_S_start_free; - } - _S_start_free = (char*) __new_alloc::allocate(__bytes_to_get); - if (_S_start_free == 0) - { - size_t __i; - _Obj* volatile* __my_free_list; - _Obj* __p; - // Try to make do with what we have. That can't hurt. We - // do not try smaller requests, since that tends to result - // in disaster on multi-process machines. - __i = __size; - for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align) - { - __my_free_list = _S_free_list + _S_freelist_index(__i); - __p = *__my_free_list; - if (__p != 0) - { - *__my_free_list = __p -> _M_free_list_link; - _S_start_free = (char*)__p; - _S_end_free = _S_start_free + __i; - return _S_chunk_alloc(__size, __nobjs); - // Any leftover piece will eventually make it to the - // right free list. - } - } - _S_end_free = 0; // In case of exception. - _S_start_free = (char*)__new_alloc::allocate(__bytes_to_get); - // This should either throw an exception or remedy the situation. - // Thus we assume it succeeded. - } - _S_heap_size += __bytes_to_get; - _S_end_free = _S_start_free + __bytes_to_get; - return _S_chunk_alloc(__size, __nobjs); - } - } - - - // Returns an object of size __n, and optionally adds to "size - // __n"'s free list. We assume that __n is properly aligned. We - // hold the allocation lock. - template<bool __threads, int __inst> - void* - __pool_alloc<__threads, __inst>::_S_refill(size_t __n) - { - int __nobjs = 20; - char* __chunk = _S_chunk_alloc(__n, __nobjs); - _Obj* volatile* __my_free_list; - _Obj* __result; - _Obj* __current_obj; - _Obj* __next_obj; - int __i; - - if (1 == __nobjs) - return __chunk; - __my_free_list = _S_free_list + _S_freelist_index(__n); - - // Build free list in chunk. - __result = (_Obj*)(void*)__chunk; - *__my_free_list = __next_obj = (_Obj*)(void*)(__chunk + __n); - for (__i = 1; ; __i++) - { - __current_obj = __next_obj; - __next_obj = (_Obj*)(void*)((char*)__next_obj + __n); - if (__nobjs - 1 == __i) - { - __current_obj -> _M_free_list_link = 0; - break; - } - else - __current_obj -> _M_free_list_link = __next_obj; - } - return __result; - } - - - template<bool __threads, int __inst> - _STL_mutex_lock - __pool_alloc<__threads,__inst>::_S_lock __STL_MUTEX_INITIALIZER; - - template<bool __threads, int __inst> - char* __pool_alloc<__threads,__inst>::_S_start_free = 0; - - template<bool __threads, int __inst> - char* __pool_alloc<__threads,__inst>::_S_end_free = 0; - - template<bool __threads, int __inst> - size_t __pool_alloc<__threads,__inst>::_S_heap_size = 0; - - template<bool __threads, int __inst> - typename __pool_alloc<__threads,__inst>::_Obj* volatile - __pool_alloc<__threads,__inst>::_S_free_list[_S_freelists]; - - typedef __pool_alloc<true,0> __alloc; - typedef __pool_alloc<false,0> __single_client_alloc; - - - /** - * @brief The "standard" allocator, as per [20.4]. - * - * The private _Alloc is "SGI" style. (See comments at the top - * of stl_alloc.h.) - * - * The underlying allocator behaves as follows. - * - __pool_alloc is used via two typedefs - * - "__single_client_alloc" typedef does no locking for threads - * - "__alloc" typedef is threadsafe via the locks - * - __new_alloc is used for memory requests - * - * (See @link Allocators allocators info @endlink for more.) - */ - template<typename _Tp> - class allocator - { - typedef __alloc _Alloc; // The underlying 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 allocator<_Tp1> other; }; - - allocator() throw() {} - allocator(const allocator&) throw() {} - template<typename _Tp1> - allocator(const allocator<_Tp1>&) throw() {} - ~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. - _Tp* - allocate(size_type __n, const void* = 0) - { - _Tp* __ret = 0; - if (__n) - { - if (__n <= this->max_size()) - __ret = static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))); - else - __throw_bad_alloc(); - } - return __ret; - } - - // __p is not permitted to be a null pointer. - void - deallocate(pointer __p, size_type __n) - { _Alloc::deallocate(__p, __n * sizeof(_Tp)); } - - size_type - max_size() const throw() { return size_t(-1) / sizeof(_Tp); } - - void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } - void destroy(pointer __p) { __p->~_Tp(); } - }; - - template<> - class allocator<void> - { - public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef void* pointer; - typedef const void* const_pointer; - typedef void value_type; - - template<typename _Tp1> - struct rebind - { typedef allocator<_Tp1> other; }; - }; - - - template<typename _T1, typename _T2> - inline bool - operator==(const allocator<_T1>&, const allocator<_T2>&) - { return true; } - - template<typename _T1, typename _T2> - inline bool - operator!=(const allocator<_T1>&, const allocator<_T2>&) - { return false; } - - - /** - * @if maint - * Allocator adaptor to turn an "SGI" style allocator (e.g., - * __alloc, __malloc_alloc) into a "standard" conforming - * allocator. Note that this adaptor does *not* assume that all - * objects of the underlying alloc class are identical, nor does it - * assume that all of the underlying alloc's member functions are - * static member functions. Note, also, that __allocator<_Tp, - * __alloc> is essentially the same thing as allocator<_Tp>. - * @endif - * (See @link Allocators allocators info @endlink for more.) - */ - template<typename _Tp, typename _Alloc> - struct __allocator - { - _Alloc __underlying_alloc; - - 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 __allocator<_Tp1, _Alloc> other; }; - - __allocator() throw() {} - __allocator(const __allocator& __a) throw() - : __underlying_alloc(__a.__underlying_alloc) {} - - template<typename _Tp1> - __allocator(const __allocator<_Tp1, _Alloc>& __a) throw() - : __underlying_alloc(__a.__underlying_alloc) {} - - ~__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. - _Tp* - allocate(size_type __n, const void* = 0) - { - _Tp* __ret = 0; - if (__n) - __ret = static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))); - return __ret; - } - - // __p is not permitted to be a null pointer. - void - deallocate(pointer __p, size_type __n) - { __underlying_alloc.deallocate(__p, __n * sizeof(_Tp)); } - - size_type - max_size() const throw() { return size_t(-1) / sizeof(_Tp); } - - void - construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } - - void - destroy(pointer __p) { __p->~_Tp(); } - }; - - template<typename _Alloc> - struct __allocator<void, _Alloc> - { - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef void* pointer; - typedef const void* const_pointer; - typedef void value_type; - - template<typename _Tp1> - struct rebind - { typedef __allocator<_Tp1, _Alloc> other; }; - }; - - template<typename _Tp, typename _Alloc> - inline bool - operator==(const __allocator<_Tp,_Alloc>& __a1, - const __allocator<_Tp,_Alloc>& __a2) - { return __a1.__underlying_alloc == __a2.__underlying_alloc; } - - template<typename _Tp, typename _Alloc> - inline bool - operator!=(const __allocator<_Tp, _Alloc>& __a1, - const __allocator<_Tp, _Alloc>& __a2) - { return __a1.__underlying_alloc != __a2.__underlying_alloc; } - - - //@{ - /** 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; } - - 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; } - //@} - - - /** - * @if maint - * Another allocator adaptor: _Alloc_traits. This serves two purposes. - * First, make it possible to write containers that can use either "SGI" - * style allocators or "standard" allocators. Second, provide a mechanism - * so that containers can query whether or not the allocator has distinct - * instances. If not, the container can avoid wasting a word of memory to - * store an empty object. For examples of use, see stl_vector.h, etc, or - * any of the other classes derived from this one. - * - * This adaptor uses partial specialization. The general case of - * _Alloc_traits<_Tp, _Alloc> assumes that _Alloc is a - * standard-conforming allocator, possibly with non-equal instances and - * non-static members. (It still behaves correctly even if _Alloc has - * static member and if all instances are equal. Refinements affect - * performance, not correctness.) - * - * There are always two members: allocator_type, which is a standard- - * conforming allocator type for allocating objects of type _Tp, and - * _S_instanceless, a static const member of type bool. If - * _S_instanceless is true, this means that there is no difference - * between any two instances of type allocator_type. Furthermore, if - * _S_instanceless is true, then _Alloc_traits has one additional - * member: _Alloc_type. This type encapsulates allocation and - * deallocation of objects of type _Tp through a static interface; it - * has two member functions, whose signatures are - * - * - static _Tp* allocate(size_t) - * - static void deallocate(_Tp*, size_t) - * - * The size_t parameters are "standard" style (see top of stl_alloc.h) in - * that they take counts, not sizes. - * - * @endif - * (See @link Allocators allocators info @endlink for more.) - */ - //@{ - // The fully general version. - template<typename _Tp, typename _Allocator> - struct _Alloc_traits - { - static const bool _S_instanceless = false; - typedef typename _Allocator::template rebind<_Tp>::other allocator_type; - }; - - template<typename _Tp, typename _Allocator> - const bool _Alloc_traits<_Tp, _Allocator>::_S_instanceless; - - /// The version for the default allocator. - template<typename _Tp, typename _Tp1> - struct _Alloc_traits<_Tp, allocator<_Tp1> > - { - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __alloc> _Alloc_type; - typedef allocator<_Tp> allocator_type; - }; - //@} - - //@{ - /// Versions for the predefined "SGI" style allocators. - template<typename _Tp, int __inst> - struct _Alloc_traits<_Tp, __malloc_alloc<__inst> > - { - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __malloc_alloc<__inst> > _Alloc_type; - typedef __allocator<_Tp, __malloc_alloc<__inst> > allocator_type; - }; - - template<typename _Tp, bool __threads, int __inst> - struct _Alloc_traits<_Tp, __pool_alloc<__threads, __inst> > - { - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __pool_alloc<__threads, __inst> > - _Alloc_type; - typedef __allocator<_Tp, __pool_alloc<__threads, __inst> > - allocator_type; - }; - - template<typename _Tp, typename _Alloc> - struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> > - { - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __debug_alloc<_Alloc> > _Alloc_type; - typedef __allocator<_Tp, __debug_alloc<_Alloc> > 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, __malloc_alloc<__inst> > > - { - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __malloc_alloc<__inst> > _Alloc_type; - typedef __allocator<_Tp, __malloc_alloc<__inst> > allocator_type; - }; - - template<typename _Tp, typename _Tp1, bool __thr, int __inst> - struct _Alloc_traits<_Tp, __allocator<_Tp1, __pool_alloc<__thr, __inst> > > - { - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __pool_alloc<__thr,__inst> > - _Alloc_type; - typedef __allocator<_Tp, __pool_alloc<__thr,__inst> > - allocator_type; - }; - - template<typename _Tp, typename _Tp1, typename _Alloc> - struct _Alloc_traits<_Tp, __allocator<_Tp1, __debug_alloc<_Alloc> > > - { - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __debug_alloc<_Alloc> > _Alloc_type; - typedef __allocator<_Tp, __debug_alloc<_Alloc> > allocator_type; - }; - //@} - - // Inhibit implicit instantiations for required instantiations, - // which are defined via explicit instantiations elsewhere. - // NB: This syntax is a GNU extension. -#if _GLIBCPP_EXTERN_TEMPLATE - extern template class allocator<char>; - extern template class allocator<wchar_t>; - extern template class __pool_alloc<true,0>; -#endif -} // namespace std - -#endif diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index 8805b7589f6..5863af55a35 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -340,7 +340,7 @@ namespace std * and destructor allocate (but don't initialize) storage. This makes * %exception safety easier. Second, the base class encapsulates all of * the differences between SGI-style allocators and standard-conforming - * allocators. (See stl_alloc.h for more on this topic.) There are two + * allocators. (See allocator.h for more on this topic.) There are two * versions: this ordinary one, and the space-saving specialization for * instanceless allocators. * @endif diff --git a/libstdc++-v3/include/bits/stl_threads.h b/libstdc++-v3/include/bits/stl_threads.h index a95fc38a423..1fb68f01e5f 100644 --- a/libstdc++-v3/include/bits/stl_threads.h +++ b/libstdc++-v3/include/bits/stl_threads.h @@ -48,6 +48,8 @@ #ifndef __SGI_STL_INTERNAL_THREADS_H #define __SGI_STL_INTERNAL_THREADS_H +#include <cstddef> + // The only supported threading model is GCC's own gthr.h abstraction layer. #include "bits/gthr.h" @@ -209,7 +211,6 @@ namespace std void operator=(const _STL_auto_lock&); _STL_auto_lock(const _STL_auto_lock&); } __attribute__ ((__unused__)); - } // namespace std #endif diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index 2965d4caab5..895b98a6a52 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -84,7 +84,7 @@ iterators invalidated are those referring to the deleted node. */ #include <bits/stl_algobase.h> -#include <bits/stl_alloc.h> +#include <bits/allocator.h> #include <bits/stl_construct.h> #include <bits/stl_function.h> diff --git a/libstdc++-v3/include/ext/debug_allocator.h b/libstdc++-v3/include/ext/debug_allocator.h new file mode 100644 index 00000000000..0f7eb0c653d --- /dev/null +++ b/libstdc++-v3/include/ext/debug_allocator.h @@ -0,0 +1,139 @@ +// Allocators -*- C++ -*- + +// Copyright (C) 2001, 2002, 2003 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) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 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. + +/* + * 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 _DEBUG_ALLOCATOR_H +#define _DEBUG_ALLOCATOR_H 1 + +#include <bits/allocator_traits.h> + +namespace __gnu_cxx +{ + /** + * @if maint + * An adaptor for an underlying allocator (_Alloc) to check the size + * arguments for debugging. + * + * "There is some evidence that this can confuse Purify." - SGI comment + * + * 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 + { + private: + // Size of space used to store size. Note that this must be + // large enough to preserve alignment. + enum {_S_extra = 8}; + + public: + static void* + allocate(size_t __n) + { + char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra); + *(size_t*)__result = __n; + return __result + (int) _S_extra; + } + + static void + deallocate(void* __p, size_t __n) + { + char* __real_p = (char*)__p - (int) _S_extra; + if (*(size_t*)__real_p != __n) + abort(); + _Alloc::deallocate(__real_p, __n + (int) _S_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 new file mode 100644 index 00000000000..410b296e09d --- /dev/null +++ b/libstdc++-v3/include/ext/malloc_allocator.h @@ -0,0 +1,163 @@ +// Allocators -*- C++ -*- + +// Copyright (C) 2001, 2002, 2003 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) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 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. + +/* + * 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> + +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 + * (See @link Allocators allocators info @endlink for more.) + */ + template<int __inst> + class __malloc_alloc + { + 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; + } + }; + + // malloc_alloc out-of-memory handling + template<int __inst> + void (* __malloc_alloc<__inst>::__malloc_alloc_oom_handler)() = 0; + + 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 + +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; + }; + //@} +} // namespace std + +#endif diff --git a/libstdc++-v3/include/ext/mt_allocator.h b/libstdc++-v3/include/ext/mt_allocator.h new file mode 100644 index 00000000000..1e95b55f467 --- /dev/null +++ b/libstdc++-v3/include/ext/mt_allocator.h @@ -0,0 +1,861 @@ +// MT-optimized allocator -*- C++ -*- + +// Copyright (C) 2003 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) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 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. + +/** @file ext/mt_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 _MT_ALLOCATOR_H +#define _MT_ALLOCATOR_H 1 + +#include <cstdlib> +#include <bits/functexcept.h> +#include <bits/stl_threads.h> +#include <bits/atomicity.h> +#include <bits/allocator_traits.h> + +/** + * 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: + * 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; + */ + +namespace __gnu_cxx +{ + template<int __inst> + class __mt_alloc + { + private: + /* + * We need to create the initial lists and set up some variables + * before we can answer to the first request for memory. + * The initialization of these variables is done at file scope + * below class declaration. + */ +#ifdef __GTHREADS + static __gthread_once_t _S_once_mt; +#endif + static bool _S_initialized; + + /* + * Using short int as type for the binmap implies we are never caching + * blocks larger than 65535 with this allocator + */ + typedef unsigned short int binmap_type; + static binmap_type* _S_binmap; + + static void _S_init(); + + /* + * Variables used to "tune" the behavior of the allocator, assigned + * and explained in detail below. + */ + static size_t _S_max_bytes; + static size_t _S_chunk_size; + static size_t _S_max_threads; + static size_t _S_no_of_bins; + static size_t _S_freelist_headroom; + + /* + * Each requesting thread is assigned an id ranging from 1 to + * _S_max_threads. Thread id 0 is used as a global memory pool. + * In order to get constant performance on the thread assignment + * routine, we keep a list of free ids. When a thread first requests + * memory we remove the first record in this list and stores the address + * in a __gthread_key. When initializing the __gthread_key + * we specify a destructor. When this destructor (i.e. the thread dies) + * is called, we return the thread id to the back of this list. + */ +#ifdef __GTHREADS + struct thread_record + { + /* + * Points to next free thread id record. NULL if last record in list. + */ + thread_record* next; + + /* + * Thread id ranging from 1 to _S_max_threads. + */ + size_t id; + }; + + static thread_record* _S_thread_freelist_first; + static thread_record* _S_thread_freelist_last; + static __gthread_mutex_t _S_thread_freelist_mutex; + static void _S_thread_key_destr(void* freelist_pos); + static __gthread_key_t _S_thread_key; + static size_t _S_get_thread_id(); +#endif + + struct block_record + { + /* + * Points to the next block_record for its thread_id. + */ + block_record* next; + + /* + * The thread id of the thread which has requested this block. + * All blocks are initially "owned" by global pool thread id 0. + */ + size_t thread_id; + }; + + struct bin_record + { + /* + * An "array" of pointers to the first/last free block for each + * thread id. Memory to these "arrays" is allocated in _S_init() + * for _S_max_threads + global pool 0. + */ + block_record** first; + block_record** last; + + /* + * An "array" of counters used to keep track of the amount of blocks + * that are on the freelist/used for each thread id. + * Memory to these "arrays" is allocated in _S_init() + * for _S_max_threads + global pool 0. + */ + size_t* free; + size_t* used; + + /* + * Each bin has its own mutex which is used to ensure data integrity + * while changing "ownership" on a block. + * The mutex is initialized in _S_init(). + */ +#ifdef __GTHREADS + __gthread_mutex_t* mutex; +#endif + }; + + /* + * An "array" of bin_records each of which represents a specific + * power of 2 size. Memory to this "array" is allocated in _S_init(). + */ + static bin_record* _S_bin; + + public: + static void* + allocate(size_t __n) + { + + /* + * Requests larger than _S_max_bytes are handled by + * malloc/free directly + */ + if (__n > _S_max_bytes) + { + void* __ret = malloc(__n); + if (!__ret) + __throw_bad_alloc(); + + return __ret; + } + + /* + * Although the test in __gthread_once() would suffice, we + * wrap test of the once condition in our own unlocked + * check. This saves one function call to pthread_once() + * (which itself only tests for the once value unlocked anyway + * and immediately returns if set) + */ + if (!_S_initialized) + { +#ifdef __GTHREADS + if (__gthread_active_p()) + __gthread_once(&_S_once_mt, _S_init); + else +#endif + { + _S_max_threads = 0; + _S_init(); + } + } + + /* + * Round up to power of 2 and figure out which bin to use + */ + size_t bin = _S_binmap[__n]; + +#ifdef __GTHREADS + size_t thread_id = _S_get_thread_id(); +#else + size_t thread_id = 0; +#endif + + block_record* block; + + /* + * Find out if we have blocks on our freelist. + * If so, go ahead and use them directly without + * having to lock anything. + */ + if (_S_bin[bin].first[thread_id] == NULL) + { + /* + * Are we using threads? + * - Yes, lock and check if there are free blocks on the global + * list (and if not add new ones), get the first one + * and change owner. + * - No, all operations are made directly to global pool 0 + * no need to lock or change ownership but check for free + * blocks on global list (and if not add new ones) and + * get the first one. + */ +#ifdef __GTHREADS + if (__gthread_active_p()) + { + __gthread_mutex_lock(_S_bin[bin].mutex); + + if (_S_bin[bin].first[0] == NULL) + { + _S_bin[bin].first[0] = + (block_record*)malloc(_S_chunk_size); + + if (!_S_bin[bin].first[0]) + { + __gthread_mutex_unlock(_S_bin[bin].mutex); + __throw_bad_alloc(); + } + + size_t bin_t = 1 << bin; + size_t block_count = + _S_chunk_size /(bin_t + sizeof(block_record)); + + _S_bin[bin].free[0] = block_count; + + block_count--; + block = _S_bin[bin].first[0]; + + while (block_count > 0) + { + block->next = (block_record*)((char*)block + + (bin_t + sizeof(block_record))); + block = block->next; + block_count--; + } + + block->next = NULL; + _S_bin[bin].last[0] = block; + } + + block = _S_bin[bin].first[0]; + + /* + * Remove from list and count down the available counter on + * global pool 0. + */ + _S_bin[bin].first[0] = _S_bin[bin].first[0]->next; + _S_bin[bin].free[0]--; + + __gthread_mutex_unlock(_S_bin[bin].mutex); + + /* + * Now that we have removed the block from the global + * freelist we can change owner and update the used + * counter for this thread without locking. + */ + block->thread_id = thread_id; + _S_bin[bin].used[thread_id]++; + } + else +#endif + { + _S_bin[bin].first[0] = (block_record*)malloc(_S_chunk_size); + + if (!_S_bin[bin].first[0]) + __throw_bad_alloc(); + + size_t bin_t = 1 << bin; + size_t block_count = + _S_chunk_size / (bin_t + sizeof(block_record)); + + _S_bin[bin].free[0] = block_count; + + block_count--; + block = _S_bin[bin].first[0]; + + while (block_count > 0) + { + block->next = (block_record*)((char*)block + + (bin_t + sizeof(block_record))); + block = block->next; + block_count--; + } + + block->next = NULL; + _S_bin[bin].last[0] = block; + + block = _S_bin[bin].first[0]; + + /* + * Remove from list and count down the available counter on + * global pool 0 and increase it's used counter. + */ + _S_bin[bin].first[0] = _S_bin[bin].first[0]->next; + _S_bin[bin].free[0]--; + _S_bin[bin].used[0]++; + } + } + else + { + /* + * "Default" operation - we have blocks on our own freelist + * grab the first record and update the counters. + */ + block = _S_bin[bin].first[thread_id]; + + _S_bin[bin].first[thread_id] = _S_bin[bin].first[thread_id]->next; + _S_bin[bin].free[thread_id]--; + _S_bin[bin].used[thread_id]++; + } + + return (void*)((char*)block + sizeof(block_record)); + } + + static void + deallocate(void* __p, size_t __n) + { + /* + * Requests larger than _S_max_bytes are handled by + * malloc/free directly + */ + if (__n > _S_max_bytes) + { + free(__p); + return; + } + + /* + * Round up to power of 2 and figure out which bin to use + */ + size_t bin = _S_binmap[__n]; + +#ifdef __GTHREADS + size_t thread_id = _S_get_thread_id(); +#else + size_t thread_id = 0; +#endif + + block_record* block = (block_record*)((char*)__p + - sizeof(block_record)); + + /* + * This block will always be at the back of a list and thus + * we set its next pointer to NULL. + */ + block->next = NULL; + +#ifdef __GTHREADS + if (__gthread_active_p()) + { + /* + * Calculate the number of records to remove from our freelist + */ + int remove = _S_bin[bin].free[thread_id] - + (_S_bin[bin].used[thread_id] / _S_freelist_headroom); + + /* + * The calculation above will almost always tell us to + * remove one or two records at a time, but this creates + * too much contention when locking and therefore we + * wait until the number of records is "high enough". + */ + if (remove > (int)(100 * (_S_no_of_bins - bin)) && + remove > (int)(_S_bin[bin].free[thread_id] / + _S_freelist_headroom)) + { + __gthread_mutex_lock(_S_bin[bin].mutex); + + while (remove > 0) + { + if (_S_bin[bin].first[0] == NULL) + _S_bin[bin].first[0] = _S_bin[bin].first[thread_id]; + else + _S_bin[bin].last[0]->next = _S_bin[bin].first[thread_id]; + + _S_bin[bin].last[0] = _S_bin[bin].first[thread_id]; + + _S_bin[bin].first[thread_id] = + _S_bin[bin].first[thread_id]->next; + + _S_bin[bin].free[0]++; + _S_bin[bin].free[thread_id]--; + + remove--; + } + + _S_bin[bin].last[0]->next = NULL; + + __gthread_mutex_unlock(_S_bin[bin].mutex); + } + + /* + * Did we allocate this block? + * - Yes, return it to our freelist + * - No, return it to global pool + */ + if (thread_id == block->thread_id) + { + if (_S_bin[bin].first[thread_id] == NULL) + _S_bin[bin].first[thread_id] = block; + else + _S_bin[bin].last[thread_id]->next = block; + + _S_bin[bin].last[thread_id] = block; + + _S_bin[bin].free[thread_id]++; + _S_bin[bin].used[thread_id]--; + } + else + { + __gthread_mutex_lock(_S_bin[bin].mutex); + + if (_S_bin[bin].first[0] == NULL) + _S_bin[bin].first[0] = block; + else + _S_bin[bin].last[0]->next = block; + + _S_bin[bin].last[0] = block; + + _S_bin[bin].free[0]++; + _S_bin[bin].used[block->thread_id]--; + + __gthread_mutex_unlock(_S_bin[bin].mutex); + } + } + else +#endif + { + /* + * Single threaded application - return to global pool + */ + if (_S_bin[bin].first[0] == NULL) + _S_bin[bin].first[0] = block; + else + _S_bin[bin].last[0]->next = block; + + _S_bin[bin].last[0] = block; + + _S_bin[bin].free[0]++; + _S_bin[bin].used[0]--; + } + } + }; + + template<int __inst> + void + __mt_alloc<__inst>:: + _S_init() + { + /* + * Calculate the number of bins required based on _S_max_bytes, + * _S_no_of_bins is initialized to 1 below. + */ + { + size_t bin_t = 1; + while (_S_max_bytes > bin_t) + { + bin_t = bin_t << 1; + _S_no_of_bins++; + } + } + + /* + * Setup the bin map for quick lookup of the relevant bin + */ + _S_binmap = (binmap_type*) + malloc ((_S_max_bytes + 1) * sizeof(binmap_type)); + + if (!_S_binmap) + __throw_bad_alloc(); + + binmap_type* bp_t = _S_binmap; + binmap_type bin_max_t = 1; + binmap_type bin_t = 0; + for (binmap_type ct = 0; ct <= _S_max_bytes; ct++) + { + if (ct > bin_max_t) + { + bin_max_t <<= 1; + bin_t++; + } + *bp_t++ = bin_t; + } + + /* + * If __gthread_active_p() create and initialize the list of + * free thread ids. Single threaded applications use thread id 0 + * directly and have no need for this. + */ +#ifdef __GTHREADS + if (__gthread_active_p()) + { + _S_thread_freelist_first = + (thread_record*)malloc(sizeof(thread_record) * _S_max_threads); + + if (!_S_thread_freelist_first) + __throw_bad_alloc(); + + /* + * NOTE! The first assignable thread id is 1 since the global + * pool uses id 0 + */ + 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].id = i; + } + + /* + * Set last record and pointer to this + */ + _S_thread_freelist_first[i - 1].next = NULL; + _S_thread_freelist_first[i - 1].id = i; + _S_thread_freelist_last = &_S_thread_freelist_first[i - 1]; + + /* + * Initialize per thread key to hold pointer to + * _S_thread_freelist NOTE! Here's an ugly workaround - if + * _S_thread_key_destr is not explicitly called at least + * once it won't be linked into the application. This is the + * behavior of template methods and __gthread_key_create() + * takes only a pointer to the function and does not cause + * the compiler to create an instance. + */ + _S_thread_key_destr(NULL); + __gthread_key_create(&_S_thread_key, _S_thread_key_destr); + } +#endif + + /* + * Initialize _S_bin and its members + */ + _S_bin = (bin_record*)malloc(sizeof(bin_record) * _S_no_of_bins); + + if (!_S_bin) + __throw_bad_alloc(); + + 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)); + + if (!_S_bin[bin].first) + __throw_bad_alloc(); + + _S_bin[bin].last = (block_record**) + malloc(sizeof(block_record*) * (_S_max_threads + 1)); + + if (!_S_bin[bin].last) + __throw_bad_alloc(); + + _S_bin[bin].free = (size_t*) + malloc(sizeof(size_t) * (_S_max_threads + 1)); + + if (!_S_bin[bin].free) + __throw_bad_alloc(); + + _S_bin[bin].used = (size_t*) + malloc(sizeof(size_t) * (_S_max_threads + 1)); + + 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(); + + /* + * This is not only ugly - it's extremly non-portable! + * However gthr.h does not currently provide a + * __gthread_mutex_init() call. The correct solution to + * this problem needs to be discussed. + */ + pthread_mutex_init(_S_bin[bin].mutex, NULL); +#endif + + for (size_t thread = 0; thread <= _S_max_threads; thread++) + { + _S_bin[bin].first[thread] = NULL; + _S_bin[bin].last[thread] = NULL; + _S_bin[bin].free[thread] = 0; + _S_bin[bin].used[thread] = 0; + } + } + + _S_initialized = true; + } + +#ifdef __GTHREADS + template<int __inst> + void + __mt_alloc<__inst>:: + _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 + * freelist we return them to the global pool here. + */ + for (size_t bin = 0; bin < _S_no_of_bins; bin++) + { + block_record* block = + _S_bin[bin].first[((thread_record*)freelist_pos)->id]; + + if (block != NULL) + { + __gthread_mutex_lock(_S_bin[bin].mutex); + + while (block != NULL) + { + if (_S_bin[bin].first[0] == NULL) + _S_bin[bin].first[0] = block; + else + _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); + } + } + + /* + * 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> + size_t + __mt_alloc<__inst>:: + _S_get_thread_id() + { + /* + * If we have thread support and it's active we check the thread + * key value and return it's id or if it's not set we take the + * first record from _S_thread_freelist and sets the key and + * returns it's id. + */ + if (__gthread_active_p()) + { + thread_record* freelist_pos; + + 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. + */ + 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); + + /* + * Since thread_ids may/will be reused (espcially in + * producer/consumer applications) we make sure that the + * list pointers and free counter is reset BUT as the + * "old" thread may still be owner of some memory (which + * is referred to by other threads and thus not freed) + * we don't reset the used counter. + */ + for (size_t bin = 0; bin < _S_no_of_bins; bin++) + { + _S_bin[bin].first[freelist_pos->id] = NULL; + _S_bin[bin].last[freelist_pos->id] = NULL; + _S_bin[bin].free[freelist_pos->id] = 0; + } + } + + return freelist_pos->id; + } + + /* + * Otherwise (no thread support or inactive) all requests are + * served from the global pool 0. + */ + return 0; + } + + template<int __inst> __gthread_once_t + __mt_alloc<__inst>::_S_once_mt = __GTHREAD_ONCE_INIT; +#endif + + template<int __inst> bool + __mt_alloc<__inst>::_S_initialized = false; + + template<int __inst> typename __mt_alloc<__inst>::binmap_type* + __mt_alloc<__inst>::_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; + + /* + * In order to avoid fragmenting and minimize the number of malloc() + * calls we always request new memory using this value. Based on + * previous discussions on the libstdc++ mailing list we have + * 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*); + + /* + * 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; + + /* + * Actual value calculated in _S_init() + */ + template<int __inst> size_t + __mt_alloc<__inst>::_S_no_of_bins = 1; + + /* + * Each time a deallocation occurs in a threaded application we make + * sure that there are no more than _S_freelist_headroom % of used + * memory on the freelist. If the number of additional records is + * 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; + + /* + * 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<int __inst> typename __mt_alloc<__inst>::thread_record* + __mt_alloc<__inst>::_S_thread_freelist_last = NULL; + + template<int __inst> __gthread_mutex_t + __mt_alloc<__inst>::_S_thread_freelist_mutex = __GTHREAD_MUTEX_INIT; + + /* + * Actual initialization in _S_init() + */ + template<int __inst> __gthread_key_t + __mt_alloc<__inst>::_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; } +} // 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/bits/stl_pthread_alloc.h b/libstdc++-v3/include/ext/new_allocator.h index 09b7d727af6..794751d3c13 100644 --- a/libstdc++-v3/include/bits/stl_pthread_alloc.h +++ b/libstdc++-v3/include/ext/new_allocator.h @@ -1,6 +1,6 @@ -// Wrapper of pthread allocation header -*- C++ -*- +// Allocators -*- C++ -*- -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002, 2003 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 @@ -27,34 +27,32 @@ // 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 stl_pthread_alloc.h - * This is an internal header file, included by other library headers. - * You should not attempt to use it directly. - */ - -#ifndef _CPP_BITS_STL_PTHREAD_ALLOC_H -#define _CPP_BITS_STL_PTHREAD_ALLOC_H 1 - -#include <bits/pthread_allocimpl.h> - -using std::_Pthread_alloc_template; -using std::pthread_alloc; - -#endif /* _CPP_BITS_STL_PTHREAD_ALLOC_H */ - -// Local Variables: -// mode:C++ -// End: +#ifndef _NEW_ALLOCATOR_H +#define _NEW_ALLOCATOR_H 1 + +#include <new> + +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 + * (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); } + }; +} // namespace __gnu_cxx + +#endif diff --git a/libstdc++-v3/include/ext/pool_allocator.h b/libstdc++-v3/include/ext/pool_allocator.h new file mode 100644 index 00000000000..77d354faabb --- /dev/null +++ b/libstdc++-v3/include/ext/pool_allocator.h @@ -0,0 +1,383 @@ +// Allocators -*- C++ -*- + +// Copyright (C) 2001, 2002, 2003 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) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 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. + +/* + * 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 _POOL_ALLOCATOR_H +#define _POOL_ALLOCATOR_H 1 + +#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 +{ + using std::_STL_mutex_lock; + using std::__throw_bad_alloc; + + /** + * @if maint + * Default node allocator. "SGI" style. Uses various allocators to + * fulfill underlying requests (and makes as few requests as possible + * when in default high-speed pool mode). + * + * Important implementation properties: + * 0. If globally mandated, then allocate objects from __new_alloc + * 1. If the clients request an object of size > _S_max_bytes, the resulting + * object will be obtained directly from __new_alloc + * 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 + * without permanently losing part of the object. + * + * The first template parameter specifies whether more than one thread may + * use this allocator. It is safe to allocate an object from one instance + * of a default_alloc and deallocate it with another one. This effectively + * transfers its ownership to the second one. This may have undesirable + * effects on reference locality. + * + * The second parameter is unused and serves only to allow the creation of + * multiple default_alloc instances. Note that containers built on different + * allocator instances have different types, limiting the utility of this + * approach. If you do not wish to share the free lists with the main + * default_alloc instance, instantiate this with a non-zero __inst. + * + * @endif + * (See @link Allocators allocators info @endlink for more.) + */ + template<bool __threads, int __inst> + class __pool_alloc + { + private: + enum {_S_align = 8}; + enum {_S_max_bytes = 128}; + enum {_S_freelists = _S_max_bytes / _S_align}; + + union _Obj + { + union _Obj* _M_free_list_link; + char _M_client_data[1]; // The client sees this. + }; + + static _Obj* volatile _S_free_list[_S_freelists]; + + // Chunk allocation state. + static char* _S_start_free; + static char* _S_end_free; + static size_t _S_heap_size; + + static _STL_mutex_lock _S_lock; + static _Atomic_word _S_force_new; + + static size_t + _S_round_up(size_t __bytes) + { return ((__bytes + (size_t)_S_align - 1) & ~((size_t)_S_align - 1)); } + + static size_t + _S_freelist_index(size_t __bytes) + { return ((__bytes + (size_t)_S_align - 1)/(size_t)_S_align - 1); } + + // Returns an object of size __n, and optionally adds to size __n + // free list. + static void* + _S_refill(size_t __n); + + // Allocates a chunk for nobjs of size size. nobjs may be reduced + // if it is inconvenient to allocate the requested number. + static char* + _S_chunk_alloc(size_t __size, int& __nobjs); + + // It would be nice to use _STL_auto_lock here. But we need a + // test whether threads are in use. + struct _Lock + { + _Lock() { if (__threads) _S_lock._M_acquire_lock(); } + ~_Lock() { if (__threads) _S_lock._M_release_lock(); } + } __attribute__ ((__unused__)); + friend struct _Lock; + + public: + // __n must be > 0 + static void* + allocate(size_t __n) + { + void* __ret = 0; + + // If there is a race through here, assume answer from getenv + // will resolve in same direction. Inspired by techniques + // to efficiently support threading found in basic_string.h. + if (_S_force_new == 0) + { + if (getenv("GLIBCPP_FORCE_NEW")) + __atomic_add(&_S_force_new, 1); + else + __atomic_add(&_S_force_new, -1); + } + + if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0)) + __ret = __new_alloc::allocate(__n); + else + { + _Obj* volatile* __my_free_list = _S_free_list + + _S_freelist_index(__n); + // Acquire the lock here with a constructor call. This + // ensures that it is released in exit or during stack + // unwinding. + _Lock __lock_instance; + _Obj* __restrict__ __result = *__my_free_list; + if (__builtin_expect(__result == 0, 0)) + __ret = _S_refill(_S_round_up(__n)); + else + { + *__my_free_list = __result -> _M_free_list_link; + __ret = __result; + } + if (__builtin_expect(__ret == 0, 0)) + __throw_bad_alloc(); + } + return __ret; + } + + // __p may not be 0 + static void + deallocate(void* __p, size_t __n) + { + if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0)) + __new_alloc::deallocate(__p, __n); + else + { + _Obj* volatile* __my_free_list = _S_free_list + + _S_freelist_index(__n); + _Obj* __q = (_Obj*)__p; + + // Acquire the lock here with a constructor call. This + // ensures that it is released in exit or during stack + // unwinding. + _Lock __lock_instance; + __q -> _M_free_list_link = *__my_free_list; + *__my_free_list = __q; + } + } + }; + + template<bool __threads, int __inst> _Atomic_word + __pool_alloc<__threads, __inst>::_S_force_new = 0; + + template<bool __threads, int __inst> + inline bool + operator==(const __pool_alloc<__threads,__inst>&, + const __pool_alloc<__threads,__inst>&) + { return true; } + + template<bool __threads, int __inst> + inline bool + operator!=(const __pool_alloc<__threads,__inst>&, + const __pool_alloc<__threads,__inst>&) + { return false; } + + + // We allocate memory in large chunks in order to avoid fragmenting the + // heap too much. We assume that __size is properly aligned. We hold + // the allocation lock. + template<bool __threads, int __inst> + char* + __pool_alloc<__threads, __inst>:: + _S_chunk_alloc(size_t __size, int& __nobjs) + { + char* __result; + size_t __total_bytes = __size * __nobjs; + size_t __bytes_left = _S_end_free - _S_start_free; + + if (__bytes_left >= __total_bytes) + { + __result = _S_start_free; + _S_start_free += __total_bytes; + return __result ; + } + else if (__bytes_left >= __size) + { + __nobjs = (int)(__bytes_left/__size); + __total_bytes = __size * __nobjs; + __result = _S_start_free; + _S_start_free += __total_bytes; + return __result; + } + else + { + size_t __bytes_to_get = + 2 * __total_bytes + _S_round_up(_S_heap_size >> 4); + // Try to make use of the left-over piece. + if (__bytes_left > 0) + { + _Obj* volatile* __my_free_list = + _S_free_list + _S_freelist_index(__bytes_left); + + ((_Obj*)(void*)_S_start_free) -> _M_free_list_link = *__my_free_list; + *__my_free_list = (_Obj*)(void*)_S_start_free; + } + _S_start_free = (char*) __new_alloc::allocate(__bytes_to_get); + if (_S_start_free == 0) + { + size_t __i; + _Obj* volatile* __my_free_list; + _Obj* __p; + // Try to make do with what we have. That can't hurt. We + // do not try smaller requests, since that tends to result + // in disaster on multi-process machines. + __i = __size; + for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align) + { + __my_free_list = _S_free_list + _S_freelist_index(__i); + __p = *__my_free_list; + if (__p != 0) + { + *__my_free_list = __p -> _M_free_list_link; + _S_start_free = (char*)__p; + _S_end_free = _S_start_free + __i; + return _S_chunk_alloc(__size, __nobjs); + // Any leftover piece will eventually make it to the + // right free list. + } + } + _S_end_free = 0; // In case of exception. + _S_start_free = (char*)__new_alloc::allocate(__bytes_to_get); + // This should either throw an exception or remedy the situation. + // Thus we assume it succeeded. + } + _S_heap_size += __bytes_to_get; + _S_end_free = _S_start_free + __bytes_to_get; + return _S_chunk_alloc(__size, __nobjs); + } + } + + + // Returns an object of size __n, and optionally adds to "size + // __n"'s free list. We assume that __n is properly aligned. We + // hold the allocation lock. + template<bool __threads, int __inst> + void* + __pool_alloc<__threads, __inst>::_S_refill(size_t __n) + { + int __nobjs = 20; + char* __chunk = _S_chunk_alloc(__n, __nobjs); + _Obj* volatile* __my_free_list; + _Obj* __result; + _Obj* __current_obj; + _Obj* __next_obj; + int __i; + + if (1 == __nobjs) + return __chunk; + __my_free_list = _S_free_list + _S_freelist_index(__n); + + // Build free list in chunk. + __result = (_Obj*)(void*)__chunk; + *__my_free_list = __next_obj = (_Obj*)(void*)(__chunk + __n); + for (__i = 1; ; __i++) + { + __current_obj = __next_obj; + __next_obj = (_Obj*)(void*)((char*)__next_obj + __n); + if (__nobjs - 1 == __i) + { + __current_obj -> _M_free_list_link = 0; + break; + } + else + __current_obj -> _M_free_list_link = __next_obj; + } + return __result; + } + + + template<bool __threads, int __inst> + _STL_mutex_lock + __pool_alloc<__threads, __inst>::_S_lock __STL_MUTEX_INITIALIZER; + + template<bool __threads, int __inst> + char* __pool_alloc<__threads, __inst>::_S_start_free = 0; + + template<bool __threads, int __inst> + char* __pool_alloc<__threads, __inst>::_S_end_free = 0; + + template<bool __threads, int __inst> + size_t __pool_alloc<__threads, __inst>::_S_heap_size = 0; + + template<bool __threads, int __inst> + typename __pool_alloc<__threads, __inst>::_Obj* volatile + __pool_alloc<__threads, __inst>::_S_free_list[_S_freelists]; +} // namespace __gnu_cxx + +namespace std +{ + //@{ + /// Versions for the predefined "SGI" style allocators. + template<typename _Tp, bool __thr, int __inst> + struct _Alloc_traits<_Tp, __gnu_cxx::__pool_alloc<__thr, __inst> > + { + static const bool _S_instanceless = true; + typedef __gnu_cxx::__pool_alloc<__thr, __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, bool __thr, int __inst> + struct _Alloc_traits<_Tp, __allocator<_Tp1, + __gnu_cxx::__pool_alloc<__thr, __inst> > > + { + static const bool _S_instanceless = true; + typedef __gnu_cxx::__pool_alloc<__thr, __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/rope b/libstdc++-v3/include/ext/rope index d621ba84aa0..9ba261845b3 100644 --- a/libstdc++-v3/include/ext/rope +++ b/libstdc++-v3/include/ext/rope @@ -53,7 +53,7 @@ #include <bits/stl_algo.h> #include <bits/stl_function.h> #include <bits/stl_numeric.h> -#include <bits/stl_alloc.h> +#include <bits/allocator.h> #include <bits/stl_construct.h> #include <bits/stl_uninitialized.h> #include <ext/hash_fun.h> diff --git a/libstdc++-v3/include/ext/slist b/libstdc++-v3/include/ext/slist index 780e2c2d693..875f7604de5 100644 --- a/libstdc++-v3/include/ext/slist +++ b/libstdc++-v3/include/ext/slist @@ -51,7 +51,7 @@ #define _SLIST 1 #include <bits/stl_algobase.h> -#include <bits/stl_alloc.h> +#include <bits/allocator.h> #include <bits/stl_construct.h> #include <bits/stl_uninitialized.h> #include <bits/concept_check.h> diff --git a/libstdc++-v3/include/std/std_deque.h b/libstdc++-v3/include/std/std_deque.h index 921c25fa493..774d334e8d7 100644 --- a/libstdc++-v3/include/std/std_deque.h +++ b/libstdc++-v3/include/std/std_deque.h @@ -65,7 +65,7 @@ #include <bits/functexcept.h> #include <bits/stl_algobase.h> -#include <bits/stl_alloc.h> +#include <bits/allocator.h> #include <bits/stl_construct.h> #include <bits/stl_uninitialized.h> #include <bits/stl_deque.h> diff --git a/libstdc++-v3/include/std/std_list.h b/libstdc++-v3/include/std/std_list.h index 84523ad8e4f..61c6dfa88eb 100644 --- a/libstdc++-v3/include/std/std_list.h +++ b/libstdc++-v3/include/std/std_list.h @@ -65,7 +65,7 @@ #include <bits/functexcept.h> #include <bits/stl_algobase.h> -#include <bits/stl_alloc.h> +#include <bits/allocator.h> #include <bits/stl_construct.h> #include <bits/stl_uninitialized.h> #include <bits/stl_list.h> diff --git a/libstdc++-v3/include/std/std_memory.h b/libstdc++-v3/include/std/std_memory.h index 47c3ede8995..b508351c8b5 100644 --- a/libstdc++-v3/include/std/std_memory.h +++ b/libstdc++-v3/include/std/std_memory.h @@ -52,7 +52,7 @@ #pragma GCC system_header #include <bits/stl_algobase.h> -#include <bits/stl_alloc.h> +#include <bits/allocator.h> #include <bits/stl_construct.h> #include <bits/stl_iterator_base_types.h> //for iterator_traits #include <bits/stl_uninitialized.h> diff --git a/libstdc++-v3/include/std/std_queue.h b/libstdc++-v3/include/std/std_queue.h index 60636e6f0dd..33eb9449727 100644 --- a/libstdc++-v3/include/std/std_queue.h +++ b/libstdc++-v3/include/std/std_queue.h @@ -65,7 +65,7 @@ #include <bits/c++config.h> #include <bits/functexcept.h> #include <bits/stl_algobase.h> -#include <bits/stl_alloc.h> +#include <bits/allocator.h> #include <bits/stl_construct.h> #include <bits/stl_uninitialized.h> #include <bits/stl_vector.h> diff --git a/libstdc++-v3/include/std/std_stack.h b/libstdc++-v3/include/std/std_stack.h index ddae7e78fc6..fb111d4d4df 100644 --- a/libstdc++-v3/include/std/std_stack.h +++ b/libstdc++-v3/include/std/std_stack.h @@ -64,7 +64,7 @@ #pragma GCC system_header #include <bits/stl_algobase.h> -#include <bits/stl_alloc.h> +#include <bits/allocator.h> #include <bits/stl_construct.h> #include <bits/stl_uninitialized.h> #include <bits/stl_deque.h> diff --git a/libstdc++-v3/include/std/std_vector.h b/libstdc++-v3/include/std/std_vector.h index 5738ef7ade8..5f700495b4c 100644 --- a/libstdc++-v3/include/std/std_vector.h +++ b/libstdc++-v3/include/std/std_vector.h @@ -65,7 +65,7 @@ #include <bits/functexcept.h> #include <bits/stl_algobase.h> -#include <bits/stl_alloc.h> +#include <bits/allocator.h> #include <bits/stl_construct.h> #include <bits/stl_uninitialized.h> #include <bits/stl_vector.h> diff --git a/libstdc++-v3/src/Makefile.am b/libstdc++-v3/src/Makefile.am index a788cb9369b..6876e288925 100644 --- a/libstdc++-v3/src/Makefile.am +++ b/libstdc++-v3/src/Makefile.am @@ -117,6 +117,7 @@ basic_file.cc: ${glibcpp_srcdir}/@BASIC_FILE_CC@ # Sources present in the src directory. sources = \ + allocator-inst.cc \ codecvt.cc \ complex_io.cc \ concept-inst.cc \ @@ -137,7 +138,6 @@ sources = \ ostream-inst.cc \ sstream-inst.cc \ stdexcept.cc \ - stl-inst.cc \ streambuf-inst.cc \ string-inst.cc \ strstream.cc \ diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in index 8e01572be71..5662b6c502f 100644 --- a/libstdc++-v3/src/Makefile.in +++ b/libstdc++-v3/src/Makefile.in @@ -121,6 +121,7 @@ enable_shared = @enable_shared@ enable_static = @enable_static@ glibcpp_CXX = @glibcpp_CXX@ glibcpp_MOFILES = @glibcpp_MOFILES@ +glibcpp_PCHFLAGS = @glibcpp_PCHFLAGS@ glibcpp_POFILES = @glibcpp_POFILES@ glibcpp_basedir = @glibcpp_basedir@ glibcpp_localedir = @glibcpp_localedir@ @@ -199,6 +200,7 @@ target_sources_extra = \ # Sources present in the src directory. sources = \ + allocator-inst.cc \ codecvt.cc \ complex_io.cc \ concept-inst.cc \ @@ -219,7 +221,6 @@ sources = \ ostream-inst.cc \ sstream-inst.cc \ stdexcept.cc \ - stl-inst.cc \ streambuf-inst.cc \ string-inst.cc \ strstream.cc \ @@ -304,15 +305,15 @@ DEFS = @DEFS@ -I. -I$(srcdir) -I.. CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ -libstdc___la_OBJECTS = codecvt.lo complex_io.lo concept-inst.lo \ -ctype.lo demangle.lo ext-inst.lo fstream-inst.lo functexcept.lo \ -globals.lo io-inst.lo ios.lo istream-inst.lo limits.lo locale.lo \ -locale-inst.lo localename.lo misc-inst.lo ostream-inst.lo \ -sstream-inst.lo stdexcept.lo stl-inst.lo streambuf-inst.lo \ -string-inst.lo strstream.lo valarray-inst.lo wstring-inst.lo \ -codecvt_members.lo collate_members.lo ctype_members.lo \ -messages_members.lo monetary_members.lo numeric_members.lo \ -time_members.lo basic_file.lo c++locale.lo +libstdc___la_OBJECTS = allocator-inst.lo codecvt.lo complex_io.lo \ +concept-inst.lo ctype.lo demangle.lo ext-inst.lo fstream-inst.lo \ +functexcept.lo globals.lo io-inst.lo ios.lo istream-inst.lo limits.lo \ +locale.lo locale-inst.lo localename.lo misc-inst.lo ostream-inst.lo \ +sstream-inst.lo stdexcept.lo streambuf-inst.lo string-inst.lo \ +strstream.lo valarray-inst.lo wstring-inst.lo codecvt_members.lo \ +collate_members.lo ctype_members.lo messages_members.lo \ +monetary_members.lo numeric_members.lo time_members.lo basic_file.lo \ +c++locale.lo CXXFLAGS = @CXXFLAGS@ CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) diff --git a/libstdc++-v3/src/allocator-inst.cc b/libstdc++-v3/src/allocator-inst.cc new file mode 100644 index 00000000000..da8aeda2452 --- /dev/null +++ b/libstdc++-v3/src/allocator-inst.cc @@ -0,0 +1,41 @@ +// Explicit instantiation file. + +// Copyright (C) 1999, 2001, 2002, 2003 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) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 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. + +// +// ISO C++ 14882: +// + +#include <bits/c++config.h> +#include <memory> + +namespace std +{ + template class allocator<char>; + template class allocator<wchar_t>; +} // namespace std diff --git a/libstdc++-v3/testsuite/ext/allocators.cc b/libstdc++-v3/testsuite/ext/allocators.cc index 3102c91bcde..34188c47328 100644 --- a/libstdc++-v3/testsuite/ext/allocators.cc +++ b/libstdc++-v3/testsuite/ext/allocators.cc @@ -1,6 +1,6 @@ // 2001-11-25 Phil Edwards <pme@gcc.gnu.org> // -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2003 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 @@ -20,27 +20,25 @@ // 20.4.1.1 allocator members -#include <memory> #include <cstdlib> +#include <memory> +#include <ext/pool_allocator.h> +#include <ext/debug_allocator.h> +#include <ext/malloc_allocator.h> #include <testsuite_hooks.h> -typedef std::__malloc_alloc<3> weird_alloc; -template class std::__malloc_alloc<3>; - -typedef std::__debug_alloc<weird_alloc> debug_weird_alloc; -template class std::__debug_alloc<weird_alloc>; - -typedef std::__pool_alloc<true, 3> unshared_normal_alloc; -template class std::__pool_alloc<true, 3>; - -typedef std::__pool_alloc<false, 3> unshared_singlethreaded; -template class std::__pool_alloc<false, 3>; +using __gnu_cxx::__malloc_alloc; +using __gnu_cxx::__debug_alloc; +using __gnu_cxx::__pool_alloc; -//std::malloc_alloc test_malloc_alloc; +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]; + long f[15]; }; @@ -63,32 +61,32 @@ operator delete(void *v) throw() return std::free(v); } - -template <typename arbitrary_SGIstyle_allocator, - bool uses_global_new_and_delete> -void test() +template<typename Alloc, bool uses_global_new_and_delete> +void check_allocator() { + bool test = true; new_called = false; delete_called = false; requested = 0; - std::__allocator<big, arbitrary_SGIstyle_allocator> a; + std::__allocator<big, Alloc> a; big *p = a.allocate(10); - if (uses_global_new_and_delete) VERIFY (requested >= (10*15*sizeof(long))); + 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 ); + VERIFY( new_called == uses_global_new_and_delete ); a.deallocate(p,10); - VERIFY (delete_called == uses_global_new_and_delete ); + VERIFY( delete_called == uses_global_new_and_delete ); } - // These just help tracking down error messages. -void test01() { test<weird_alloc,false>(); } -void test02() { test<debug_weird_alloc,false>(); } -void test03() { test<unshared_normal_alloc,true>(); } -void test04() { test<unshared_singlethreaded,true>(); } +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>(); } int main() { @@ -96,7 +94,6 @@ int main() test02(); test03(); test04(); - return 0; } diff --git a/libstdc++-v3/testsuite/ext/headers.cc b/libstdc++-v3/testsuite/ext/headers.cc index a2c1233302d..52f6028bd12 100644 --- a/libstdc++-v3/testsuite/ext/headers.cc +++ b/libstdc++-v3/testsuite/ext/headers.cc @@ -1,6 +1,6 @@ // 1999-06-23 bkoz -// Copyright (C) 1999, 2001 Free Software Foundation, Inc. +// Copyright (C) 1999, 2001, 2003 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 @@ -33,5 +33,11 @@ #include <ext/rb_tree> #include <ext/rope> #include <ext/slist> +#include <ext/debug_allocator.h> +#include <ext/malloc_allocator.h> +#include <ext/mt_allocator.h> +#include <ext/pool_allocator.h> +#include <ext/stdio_filebuf.h> +#include <ext/stdio_sync_filebuf.h> int main() { } |