From: Benjamin Kosnik Date: Thu, 5 Dec 2002 23:48:57 +0000 (+0000) Subject: [multiple changes] X-Git-Tag: releases/gcc-3.2.2~207 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=367cf8c891859166959580f3eb4d5bcf183326e3;p=thirdparty%2Fgcc.git [multiple changes] 2002-12-05 Benjamin Kosnik * config/linker-map.gnu: Put _S_force_new into GLIBCPP_3.2.2. * testsuite/abi_check.cc: Add GLIBCPP_3.2.2. 2002-12-05 Benjamin Kosnik Gabriel Dos Reis PR libstdc++/8230 * include/bits/stl_alloc.h: Use builtin_expect for the most obvious limit checks. (__default_alloc_template::allocate): Check for null, throw bad_alloc. * testsuite/20_util/allocator_members.cc (test02): Add. * testsuite/23_containers/vector_capacity.cc (test03): Add. 2002-12-05 Loren J. Rittle Brad Spencer (provided alternate patch and improvements) PR libstdc++/8708 * docs/html/23_containers/howto.html (GLIBCPP_FORCE_NEW): Document new environment variable which replaces all uses of __USE_MALLOC macro. * docs/html/ext/howto.html (GLIBCPP_FORCE_NEW): Likewise. (__mem_interface): Remove all references to old internal typedef. * include/backward/alloc.h (__USE_MALLOC): Remove it and all guarded code. * include/bits/c++config (__USE_MALLOC): Update related error message and comment. * include/bits/stl_alloc.h (__USE_MALLOC): Remove it and all guarded code. Update all related comments. (__mem_interface): Unconditionally replace it with __new_alloc. However, leave the typedef around in case anyone used it. (__default_alloc_template<>::_S_force_new): New class static. (__default_alloc_template<>::allocate, deallocate): Add run-time controlled feature similar to what __USE_MALLOC code path had provided. * src/stl-inst.cc (__USE_MALLOC): Remove it and all guarded code. * testsuite/21_strings/capacity.cc: Remove reference to __USE_MALLOC. Add documentation on GLIBCPP_FORCE_NEW environment variable. * testsuite/ext/allocators.cc: Likewise. From-SVN: r59873 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index bac4c721a11b..d3e059243a0e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,47 @@ +2002-12-05 Benjamin Kosnik + + * config/linker-map.gnu: Put _S_force_new into GLIBCPP_3.2.2. + * testsuite/abi_check.cc: Add GLIBCPP_3.2.2. + +2002-12-05 Benjamin Kosnik + Gabriel Dos Reis + + PR libstdc++/8230 + * include/bits/stl_alloc.h: Use builtin_expect for the most + obvious limit checks. + (__default_alloc_template::allocate): Check for null, throw + bad_alloc. + * testsuite/20_util/allocator_members.cc (test02): Add. + * testsuite/23_containers/vector_capacity.cc (test03): Add. + +2002-12-05 Loren J. Rittle + Brad Spencer + (provided alternate patch and improvements) + + PR libstdc++/8708 + * docs/html/23_containers/howto.html (GLIBCPP_FORCE_NEW): Document + new environment variable which replaces all uses of __USE_MALLOC + macro. + * docs/html/ext/howto.html (GLIBCPP_FORCE_NEW): Likewise. + (__mem_interface): Remove all references to old internal typedef. + * include/backward/alloc.h (__USE_MALLOC): Remove it and all + guarded code. + * include/bits/c++config (__USE_MALLOC): Update related error + message and comment. + * include/bits/stl_alloc.h (__USE_MALLOC): Remove it and all + guarded code. Update all related comments. + (__mem_interface): Unconditionally replace it with __new_alloc. + However, leave the typedef around in case anyone used it. + (__default_alloc_template<>::_S_force_new): New class static. + (__default_alloc_template<>::allocate, deallocate): Add + run-time controlled feature similar to what __USE_MALLOC code + path had provided. + * src/stl-inst.cc (__USE_MALLOC): Remove it and all + guarded code. + * testsuite/21_strings/capacity.cc: Remove reference to __USE_MALLOC. + Add documentation on GLIBCPP_FORCE_NEW environment variable. + * testsuite/ext/allocators.cc: Likewise. + 2002-12-05 Paolo Carlini Nathan Myers diff --git a/libstdc++-v3/config/linker-map.gnu b/libstdc++-v3/config/linker-map.gnu index f82002acd513..8f7793fca4e7 100644 --- a/libstdc++-v3/config/linker-map.gnu +++ b/libstdc++-v3/config/linker-map.gnu @@ -204,8 +204,6 @@ GLIBCPP_3.2.1 { _ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_; _ZStplIwSt11char_traitsIwESaIwEESbIT_T0_T1_ERKS6_S8_; - _ZNSt24__default_alloc_templateILb1ELi0EE12_S_force_newE; - # stub functions from libmath sinf; sinl; @@ -242,6 +240,12 @@ GLIBCPP_3.2.1 { } GLIBCPP_3.2; +GLIBCPP_3.2.2 { + + _ZNSt24__default_alloc_templateILb1ELi0EE12_S_force_newE; + +} GLIBCPP_3.2.1; + # Symbols in the support library (libsupc++) have their own tag. CXXABI_1.2 { diff --git a/libstdc++-v3/docs/html/23_containers/howto.html b/libstdc++-v3/docs/html/23_containers/howto.html index 1c1e137b67c9..27314fbafc3d 100644 --- a/libstdc++-v3/docs/html/23_containers/howto.html +++ b/libstdc++-v3/docs/html/23_containers/howto.html @@ -1,4 +1,9 @@ - + + + + @@ -247,41 +252,11 @@ solution would probably be more trouble than it's worth.

The STL implementation is currently configured to use the - high-speed caching memory allocator. If you absolutely think - you must change this on a global basis for your platform to better - support multi-threading, then please consult all commentary in - include/bits/stl_alloc.h and the allocators link below. + high-speed caching memory allocator. Some people like to + test and/or normally run threaded programs with a different + default. For all details about how to globally override this + at application run-time see here.

-
-

(Explicit warning since so many people get confused while - attempting this:) -

-

Adding -D__USE_MALLOC on the command - line is almost certainly a bad idea. Memory efficiency is - almost guaranteed to suffer as a result; this is - why - we disabled it for 3.0 in the first place. -

-

Related to threading or otherwise, the current recommendation is - that users not add any macro defines on the command line to remove or - otherwise disable features of libstdc++-v3. There is - no condition under which it will help you without causing other - issues to perhaps raise up (possible linkage/ABI problems). In - particular, __USE_MALLOC should only be added to a libstdc++-v3 - configuration file, include/bits/c++config (where such user - action is cautioned against), and the entire library should be - rebuilt. If you do not, then you might be violating the - one-definition rule of C/C++ and you might cause yourself untold - problems. -

-
-

If you find any platform where gcc reports a - threading model other than single, and where libstdc++-v3 builds - a buggy container allocator when used with threads unless you - define __USE_MALLOC, we want to hear about it ASAP. In the - past, correctness was the main reason people were led to believe - that they should define __USE_MALLOC when using threads. -

There is a better way (not standardized yet): It is possible to force the malloc-based allocator on a per-case-basis for some application code. The library team generally believes that this diff --git a/libstdc++-v3/docs/html/ext/howto.html b/libstdc++-v3/docs/html/ext/howto.html index b4f6dae6f146..3d08c5703854 100644 --- a/libstdc++-v3/docs/html/ext/howto.html +++ b/libstdc++-v3/docs/html/ext/howto.html @@ -1,4 +1,9 @@ - + + + + @@ -276,19 +281,16 @@ same as allocator<T>. -

An internal typedef, __mem_interface , is defined to be - __new_alloc by default. -

Normally, __default_alloc_template<bool thr, int inst> is also available. This is the high-speed pool, called the default node allocator. The reusable memory is shared among identical instantiations of - this type. It calls through __mem_interface to obtain + this type. It calls through __new_alloc to obtain new memory when its lists run out. If a client container requests a block larger than a certain threshold size, then the pool is bypassed, and the allocate/deallocate request is passed to - __mem_interface directly. + __new_alloc directly.

Its inst parameter is described below. The thr boolean determines whether the pool should be @@ -309,17 +311,25 @@

A cannon to swat a fly: __USE_MALLOC

If you've already read this - advice and decided to define this macro, then the situation changes - thusly: -

-
    -
  1. __mem_interface, and
  2. -
  3. __alloc, and
  4. -
  5. __single_client_alloc are all typedef'd to - __malloc_alloc_template.
  6. -
  7. __default_alloc_template is no longer available. - At all. Anywhere.
  8. -
+ advice but still think you remember how to use this macro from + SGI STL days. We have removed it in gcc 3.3. See next section + for the new way to get the same effect. +

+

Globally disabling memory caching: GLIBCPP_FORCE_NEW

+

Starting with gcc 3.3, if you want to globally disable memory + caching within the library for the default allocator (i.e. + the one you get for all library objects when you do not specify + which one to use), merely set GLIBCPP_FORCE_NEW (at this time, + with any value) into your environment before running the + program. You will obtain a similar effect without having to + recompile your entire program and the entire library (the new + operator in gcc is a light wrapper around malloc). If your + program crashes with GLIBCPP_FORCE_NEW in the environment, + it likely means that you linked against objects built against + the older library. Code to support this extension is fully + compatible with 3.2 code if GLIBCPP_FORCE_NEW is not in the + environment. +

Writing your own allocators

Depending on your application (a specific program, a generic library, etc), allocator classes tend to be one of two styles: "SGI" diff --git a/libstdc++-v3/include/backward/alloc.h b/libstdc++-v3/include/backward/alloc.h index 4344a1d902c9..9482e4cfebad 100644 --- a/libstdc++-v3/include/backward/alloc.h +++ b/libstdc++-v3/include/backward/alloc.h @@ -53,10 +53,6 @@ using std::__debug_alloc; using std::__alloc; using std::__single_client_alloc; using std::allocator; -#ifdef __USE_MALLOC -using std::malloc_alloc; -#else using std::__default_alloc_template; -#endif #endif diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 61a49df308c6..6f2b7e2db9ce 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -74,13 +74,8 @@ // so, please report any possible issues to libstdc++@gcc.gnu.org . // Do not define __USE_MALLOC on the command line. Enforce it here: #ifdef __USE_MALLOC -#error __USE_MALLOC should only be defined within \ -libstdc++-v3/include/bits/c++config before full recompilation of the library. +#error __USE_MALLOC should never be defined. Read the release notes. #endif -// Define __USE_MALLOC after this point in the file in order to aid debugging -// or globally change allocation policy. This breaks the ABI, thus -// completely recompile the library. A patch to better support -// changing the global allocator policy would be probably be accepted. // The remainder of the prewritten config is mostly automatic; all the // user hooks are listed above. diff --git a/libstdc++-v3/include/bits/stl_alloc.h b/libstdc++-v3/include/bits/stl_alloc.h index 7c34000401c1..238986d7eeb6 100644 --- a/libstdc++-v3/include/bits/stl_alloc.h +++ b/libstdc++-v3/include/bits/stl_alloc.h @@ -74,6 +74,10 @@ * into a "standard" one. * @endif * + * @note The @c reallocate member functions have been deprecated for 3.2 + * and will be removed in 3.4. You must define @c _GLIBCPP_DEPRECATED + * to make this visible in 3.2; see c++config.h. + * * 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 */ @@ -85,6 +89,8 @@ #include // For __throw_bad_alloc #include +#include + namespace std { /** @@ -94,19 +100,19 @@ namespace std * reallocate(). * @endif * (See @link Allocators allocators info @endlink for more.) - */ - class __new_alloc + */ + class __new_alloc { public: - static void* + static void* allocate(size_t __n) { return ::operator new(__n); } - - static void + + static void deallocate(void* __p, size_t) { ::operator delete(__p); } }; - + /** * @if maint @@ -117,121 +123,134 @@ namespace std * for caveats). "SGI" style, plus __set_malloc_handler for OOM conditions. * @endif * (See @link Allocators allocators info @endlink for more.) - */ - template - class __malloc_alloc_template + */ + template + class __malloc_alloc_template { private: static void* _S_oom_malloc(size_t); + + // _GLIBCPP_DEPRECATED static void* _S_oom_realloc(void*, size_t); + static void (* __malloc_alloc_oom_handler)(); - + public: - static void* + static void* allocate(size_t __n) { - void* __result = malloc(__n); - if (0 == __result) __result = _S_oom_malloc(__n); - return __result; + void* __result = malloc(__n); + if (__builtin_expect(__result == 0, 0)) + __result = _S_oom_malloc(__n); + return __result; } - static void + static void deallocate(void* __p, size_t /* __n */) { free(__p); } - static void* + // _GLIBCPP_DEPRECATED + static void* reallocate(void* __p, size_t /* old_sz */, size_t __new_sz) { - void* __result = realloc(__p, __new_sz); - if (0 == __result) __result = _S_oom_realloc(__p, __new_sz); - return __result; + void* __result = realloc(__p, __new_sz); + if (__builtin_expect(__result == 0, 0)) + __result = _S_oom_realloc(__p, __new_sz); + return __result; } - + static void (* __set_malloc_handler(void (*__f)()))() { - void (* __old)() = __malloc_alloc_oom_handler; - __malloc_alloc_oom_handler = __f; - return(__old); + void (* __old)() = __malloc_alloc_oom_handler; + __malloc_alloc_oom_handler = __f; + return __old; } }; // malloc_alloc out-of-memory handling - template + template void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0; - template + template void* - __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n) + __malloc_alloc_template<__inst>:: + _S_oom_malloc(size_t __n) { void (* __my_malloc_handler)(); void* __result; - - for (;;) - { - __my_malloc_handler = __malloc_alloc_oom_handler; - if (0 == __my_malloc_handler) - std::__throw_bad_alloc(); - (*__my_malloc_handler)(); - __result = malloc(__n); - if (__result) - return(__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; + } } - - template - void* - __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n) - { + + // _GLIBCPP_DEPRECATED + template + void* + __malloc_alloc_template<__inst>:: + _S_oom_realloc(void* __p, size_t __n) + { void (* __my_malloc_handler)(); void* __result; - - for (;;) - { - __my_malloc_handler = __malloc_alloc_oom_handler; - if (0 == __my_malloc_handler) - std::__throw_bad_alloc(); - (*__my_malloc_handler)(); - __result = realloc(__p, __n); - if (__result) - return(__result); - } - } + for (;;) + { + __my_malloc_handler = __malloc_alloc_oom_handler; + if (__builtin_expect(__my_malloc_handler == 0, 0)) + __throw_bad_alloc(); + (*__my_malloc_handler)(); + __result = realloc(__p, __n); + if (__result) + return __result; + } + } -// Determines the underlying allocator choice for the node allocator. -#ifdef __USE_MALLOC - typedef __malloc_alloc_template<0> __mem_interface; -#else + // Should not be referenced within the library anymore. typedef __new_alloc __mem_interface; -#endif - /** * @if maint * This is used primarily (only?) in _Alloc_traits and other places to - * help provide the _Alloc_type typedef. + * 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 - class __simple_alloc - { - public: - static _Tp* allocate(size_t __n) - { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); } - - 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)); } - }; + */ + template + 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)); } + }; /** @@ -247,273 +266,290 @@ namespace std * This adaptor is "SGI" style. The _Alloc parameter must also be "SGI". * @endif * (See @link Allocators allocators info @endlink for more.) - */ - template - class __debug_alloc - { - private: - enum {_S_extra = 8}; // Size of space used to store size. Note that this - // must be large enough to preserve alignment. - - 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) + */ + template + class __debug_alloc { - char* __real_p = (char*)__p - (int) _S_extra; - assert(*(size_t*)__real_p == __n); - _Alloc::deallocate(__real_p, __n + (int) _S_extra); - } - - static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz) + 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; + assert(*(size_t*)__real_p == __n); + _Alloc::deallocate(__real_p, __n + (int) _S_extra); + } + + // _GLIBCPP_DEPRECATED + static void* + reallocate(void* __p, size_t __old_sz, size_t __new_sz) + { + char* __real_p = (char*)__p - (int) _S_extra; + assert(*(size_t*)__real_p == __old_sz); + char* __result = (char*) _Alloc::reallocate(__real_p, + __old_sz + (int) _S_extra, + __new_sz + (int) _S_extra); + *(size_t*)__result = __new_sz; + return __result + (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 > _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 + class __default_alloc_template { - char* __real_p = (char*)__p - (int) _S_extra; - assert(*(size_t*)__real_p == __old_sz); - char* __result = (char*) - _Alloc::reallocate(__real_p, __old_sz + (int) _S_extra, - __new_sz + (int) _S_extra); - *(size_t*)__result = __new_sz; - return __result + (int) _S_extra; - } - }; + private: + enum {_ALIGN = 8}; + enum {_MAX_BYTES = 128}; + enum {_NFREELISTS = _MAX_BYTES / _ALIGN}; + union _Obj + { + union _Obj* _M_free_list_link; + char _M_client_data[1]; // The client sees this. + }; -#ifdef __USE_MALLOC + static _Obj* volatile _S_free_list[_NFREELISTS]; -typedef __mem_interface __alloc; -typedef __mem_interface __single_client_alloc; + // Chunk allocation state. + static char* _S_start_free; + static char* _S_end_free; + static size_t _S_heap_size; -#else + static _STL_mutex_lock _S_node_allocator_lock; + static size_t + _S_round_up(size_t __bytes) + { return (((__bytes) + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1)); } -/** - * @if maint - * Default node allocator. "SGI" style. Uses __mem_interface for its - * underlying requests (and makes as few requests as possible). - * **** Currently __mem_interface is always __new_alloc, never __malloc*. - * - * Important implementation properties: - * 1. If the clients request an object of size > _MAX_BYTES, the resulting - * object will be obtained directly from the underlying __mem_interface. - * 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 - class __default_alloc_template - { - private: - enum {_ALIGN = 8}; - enum {_MAX_BYTES = 128}; - enum {_NFREELISTS = _MAX_BYTES / _ALIGN}; - - union _Obj - { - union _Obj* _M_free_list_link; - char _M_client_data[1]; // The client sees this. - }; + static size_t + _S_freelist_index(size_t __bytes) + { return (((__bytes) + (size_t)_ALIGN - 1)/(size_t)_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_node_allocator_lock._M_acquire_lock(); } + ~_Lock() { if (__threads) _S_node_allocator_lock._M_release_lock(); } + } __attribute__ ((__unused__)); + friend struct _Lock; + + static _Atomic_word _S_force_new; - static _Obj* volatile _S_free_list[_NFREELISTS]; - - // Chunk allocation state. - static char* _S_start_free; - static char* _S_end_free; - static size_t _S_heap_size; - - static _STL_mutex_lock _S_node_allocator_lock; - - static size_t - _S_round_up(size_t __bytes) - { return (((__bytes) + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1)); } - - static size_t - _S_freelist_index(size_t __bytes) - { return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_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. - class _Lock - { public: - _Lock() { if (__threads) _S_node_allocator_lock._M_acquire_lock(); } - ~_Lock() { if (__threads) _S_node_allocator_lock._M_release_lock(); } - } __attribute__ ((__unused__)); - friend class _Lock; - - public: - // __n must be > 0 - static void* - allocate(size_t __n) - { - void* __ret = 0; - - if (__n > (size_t) _MAX_BYTES) - __ret = __mem_interface::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 (__result == 0) - __ret = _S_refill(_S_round_up(__n)); - else - { - *__my_free_list = __result -> _M_free_list_link; - __ret = __result; - } - } - return __ret; - }; + // __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); + // Trust but verify... + assert(_S_force_new != 0); + } + + if ((__n > (size_t) _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) _MAX_BYTES) - __mem_interface::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; - } - } - - static void* - reallocate(void* __p, size_t __old_sz, size_t __new_sz); - }; + // __p may not be 0 + static void + deallocate(void* __p, size_t __n) + { + if ((__n > (size_t) _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; + } + } + + // _GLIBCPP_DEPRECATED + static void* + reallocate(void* __p, size_t __old_sz, size_t __new_sz); + }; + template _Atomic_word + __default_alloc_template<__threads, __inst>::_S_force_new = 0; template - inline bool - operator==(const __default_alloc_template<__threads, __inst>&, - const __default_alloc_template<__threads, __inst>&) + inline bool + operator==(const __default_alloc_template<__threads,__inst>&, + const __default_alloc_template<__threads,__inst>&) { return true; } template - inline bool - operator!=(const __default_alloc_template<__threads, __inst>&, - const __default_alloc_template<__threads, __inst>&) + inline bool + operator!=(const __default_alloc_template<__threads,__inst>&, + const __default_alloc_template<__threads,__inst>&) { return false; } // We allocate memory in large chunks in order to avoid fragmenting the - // malloc heap (or whatever __mem_interface is using) too much. We assume - // that __size is properly aligned. We hold the allocation lock. + // heap too much. We assume that __size is properly aligned. We hold + // the allocation lock. template char* - __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size, - int& __nobjs) + __default_alloc_template<__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*)_S_start_free) -> _M_free_list_link = *__my_free_list; - *__my_free_list = (_Obj*)_S_start_free; - } - _S_start_free = (char*) __mem_interface::allocate(__bytes_to_get); - if (0 == _S_start_free) - { - 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) _MAX_BYTES; __i += (size_t) _ALIGN) - { - __my_free_list = _S_free_list + _S_freelist_index(__i); - __p = *__my_free_list; - if (0 != __p) - { - *__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*)__mem_interface::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)); - } + + 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*)_S_start_free) -> _M_free_list_link = *__my_free_list; + *__my_free_list = (_Obj*)_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) _MAX_BYTES; __i += (size_t) _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. @@ -528,414 +564,421 @@ template _Obj* __current_obj; _Obj* __next_obj; int __i; - - if (1 == __nobjs) return(__chunk); + + if (1 == __nobjs) + return __chunk; __my_free_list = _S_free_list + _S_freelist_index(__n); - - /* Build free list in chunk */ + + // 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 -> _M_free_list_link = 0; - break; - } else { - __current_obj -> _M_free_list_link = __next_obj; - } - } - return(__result); + for (__i = 1; ; __i++) + { + __current_obj = __next_obj; + __next_obj = (_Obj*)((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; } + // _GLIBCPP_DEPRECATED template void* - __default_alloc_template::reallocate(void* __p, - size_t __old_sz, - size_t __new_sz) + __default_alloc_template:: + reallocate(void* __p, size_t __old_sz, size_t __new_sz) { void* __result; size_t __copy_sz; - - if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) { + + if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) return(realloc(__p, __new_sz)); - } - if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return(__p); + 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); + return __result; } - + template - _STL_mutex_lock - __default_alloc_template<__threads, __inst>::_S_node_allocator_lock - __STL_MUTEX_INITIALIZER; - + _STL_mutex_lock + __default_alloc_template<__threads,__inst>::_S_node_allocator_lock + __STL_MUTEX_INITIALIZER; + template - char* __default_alloc_template<__threads, __inst>::_S_start_free = 0; - + char* __default_alloc_template<__threads,__inst>::_S_start_free = 0; + template - char* __default_alloc_template<__threads, __inst>::_S_end_free = 0; - + char* __default_alloc_template<__threads,__inst>::_S_end_free = 0; + template - size_t __default_alloc_template<__threads, __inst>::_S_heap_size = 0; - + size_t __default_alloc_template<__threads,__inst>::_S_heap_size = 0; + template - typename __default_alloc_template<__threads, __inst>::_Obj* volatile - __default_alloc_template<__threads, __inst>::_S_free_list[_NFREELISTS]; - - typedef __default_alloc_template __alloc; - typedef __default_alloc_template __single_client_alloc; + typename __default_alloc_template<__threads,__inst>::_Obj* volatile + __default_alloc_template<__threads,__inst>::_S_free_list[_NFREELISTS]; + typedef __default_alloc_template __alloc; + typedef __default_alloc_template __single_client_alloc; -#endif /* ! __USE_MALLOC */ + /** + * @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. + * - __default_alloc_template 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 + 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 + struct rebind + { typedef allocator<_Tp1> other; }; + + allocator() throw() {} + allocator(const allocator&) throw() {} + template + 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; + } -/** - * This is a "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. - * - if __USE_MALLOC then - * - thread safety depends on malloc and is entirely out of our hands - * - __malloc_alloc_template is used for memory requests - * - else (the default) - * - __default_alloc_template 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 -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 struct rebind { - typedef allocator<_Tp1> other; - }; + // __p is not permitted to be a null pointer. + void + deallocate(pointer __p, size_type __n) + { _Alloc::deallocate(__p, __n * sizeof(_Tp)); } - allocator() throw() {} - allocator(const allocator&) throw() {} - template allocator(const allocator<_Tp1>&) throw() {} - ~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*>(_Alloc::allocate(__n * sizeof(_Tp))) - : 0; - } - - // __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 { -public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef void* pointer; - typedef const void* const_pointer; - typedef void value_type; - - template struct rebind { - typedef allocator<_Tp1> other; - }; -}; + 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 -inline bool operator==(const allocator<_T1>&, const allocator<_T2>&) -{ - return true; -} + template<> + class allocator + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + template + struct rebind + { typedef allocator<_Tp1> other; }; + }; -template -inline bool operator!=(const allocator<_T1>&, const allocator<_T2>&) -{ - return false; -} + template + inline bool + operator==(const allocator<_T1>&, const allocator<_T2>&) + { return true; } -/** - * @if maint - * Allocator adaptor to turn an "SGI" style allocator (e.g., __alloc, - * __malloc_alloc_template) 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 -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 struct rebind { - typedef __allocator<_Tp1, _Alloc> other; - }; + template + inline bool + operator!=(const allocator<_T1>&, const allocator<_T2>&) + { return false; } - __allocator() throw() {} - __allocator(const __allocator& __a) throw() - : __underlying_alloc(__a.__underlying_alloc) {} - template - __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; } - - // __n is permitted to be 0. - _Tp* allocate(size_type __n, const void* = 0) { - return __n != 0 - ? static_cast<_Tp*>(__underlying_alloc.allocate(__n * sizeof(_Tp))) - : 0; - } - - // __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 -class __allocator { - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef void* pointer; - typedef const void* const_pointer; - typedef void value_type; - - template struct rebind { - typedef __allocator<_Tp1, _Alloc> other; - }; -}; -template -inline bool operator==(const __allocator<_Tp, _Alloc>& __a1, - const __allocator<_Tp, _Alloc>& __a2) -{ - return __a1.__underlying_alloc == __a2.__underlying_alloc; -} + /** + * @if maint + * Allocator adaptor to turn an "SGI" style allocator (e.g., + * __alloc, __malloc_alloc_template) 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 + 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 + struct rebind + { typedef __allocator<_Tp1, _Alloc> other; }; + + __allocator() throw() {} + __allocator(const __allocator& __a) throw() + : __underlying_alloc(__a.__underlying_alloc) {} + + template + __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; + } -template -inline bool operator!=(const __allocator<_Tp, _Alloc>& __a1, - const __allocator<_Tp, _Alloc>& __a2) -{ - return __a1.__underlying_alloc != __a2.__underlying_alloc; -} + // __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 + struct __allocator + { + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + template + struct rebind + { typedef __allocator<_Tp1, _Alloc> other; }; + }; -//@{ -/** Comparison operators for all of the predifined SGI-style allocators. - * This ensures that __allocator (for example) will work - * correctly. As required, all allocators compare equal. -*/ -template -inline bool operator==(const __malloc_alloc_template&, - const __malloc_alloc_template&) -{ - return true; -} + template + inline bool + operator==(const __allocator<_Tp,_Alloc>& __a1, + const __allocator<_Tp,_Alloc>& __a2) + { return __a1.__underlying_alloc == __a2.__underlying_alloc; } + + template + 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 (for example) will work + * correctly. As required, all allocators compare equal. + */ + template + inline bool + operator==(const __malloc_alloc_template&, + const __malloc_alloc_template&) + { return true; } -template -inline bool operator!=(const __malloc_alloc_template<__inst>&, - const __malloc_alloc_template<__inst>&) -{ - return false; -} + template + inline bool + operator!=(const __malloc_alloc_template<__inst>&, + const __malloc_alloc_template<__inst>&) + { return false; } -template -inline bool operator==(const __debug_alloc<_Alloc>&, - const __debug_alloc<_Alloc>&) { - return true; -} + template + inline bool + operator==(const __debug_alloc<_Alloc>&, const __debug_alloc<_Alloc>&) + { return true; } -template -inline bool operator!=(const __debug_alloc<_Alloc>&, - const __debug_alloc<_Alloc>&) { - return false; -} -//@} + template + 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 -struct _Alloc_traits -{ - static const bool _S_instanceless = false; - typedef typename _Allocator::template rebind<_Tp>::other allocator_type; -}; + /** + * @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 + struct _Alloc_traits + { + static const bool _S_instanceless = false; + typedef typename _Allocator::template rebind<_Tp>::other allocator_type; + }; -template -const bool _Alloc_traits<_Tp, _Allocator>::_S_instanceless; + template + const bool _Alloc_traits<_Tp, _Allocator>::_S_instanceless; -/// The version for the default allocator. -template -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 -struct _Alloc_traits<_Tp, __malloc_alloc_template<__inst> > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type; - typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; -}; - -#ifndef __USE_MALLOC -template -struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __default_alloc_template<__threads, __inst> > - _Alloc_type; - typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> > - allocator_type; -}; -#endif + /// The version for the default allocator. + template + struct _Alloc_traits<_Tp, allocator<_Tp1> > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __alloc> _Alloc_type; + typedef allocator<_Tp> allocator_type; + }; + //@} -template -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 -struct _Alloc_traits<_Tp, - __allocator<_Tp1, __malloc_alloc_template<__inst> > > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type; - typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; -}; - -#ifndef __USE_MALLOC -template -struct _Alloc_traits<_Tp, - __allocator<_Tp1, - __default_alloc_template<__thr, __inst> > > -{ - static const bool _S_instanceless = true; - typedef __simple_alloc<_Tp, __default_alloc_template<__thr,__inst> > - _Alloc_type; - typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> > - allocator_type; -}; -#endif + //@{ + /// Versions for the predefined "SGI" style allocators. + template + struct _Alloc_traits<_Tp, __malloc_alloc_template<__inst> > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type; + typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; + }; -template -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; -}; -//@} + template + struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __default_alloc_template<__threads, __inst> > + _Alloc_type; + typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> > + allocator_type; + }; + + template + 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 + struct _Alloc_traits<_Tp, + __allocator<_Tp1, __malloc_alloc_template<__inst> > > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type; + typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; + }; + + template + struct _Alloc_traits<_Tp, __allocator<_Tp1, __default_alloc_template<__thr, __inst> > > + { + static const bool _S_instanceless = true; + typedef __simple_alloc<_Tp, __default_alloc_template<__thr,__inst> > + _Alloc_type; + typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> > + allocator_type; + }; + + template + 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. + // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. extern template class allocator; extern template class allocator; -#ifdef __USE_MALLOC - extern template class __malloc_alloc_template<0>; -#else - extern template class __default_alloc_template; -#endif + extern template class __default_alloc_template; } // namespace std -#endif /* __GLIBCPP_INTERNAL_ALLOC_H */ - -// Local Variables: -// mode:C++ -// End: +#endif diff --git a/libstdc++-v3/src/stl-inst.cc b/libstdc++-v3/src/stl-inst.cc index d8879a7bccd8..d80a71867184 100644 --- a/libstdc++-v3/src/stl-inst.cc +++ b/libstdc++-v3/src/stl-inst.cc @@ -39,9 +39,5 @@ namespace std template class allocator; template class allocator; -#ifdef __USE_MALLOC - template class __malloc_alloc_template<0>; -#else template class __default_alloc_template; -#endif } // namespace std diff --git a/libstdc++-v3/testsuite/20_util/allocator_members.cc b/libstdc++-v3/testsuite/20_util/allocator_members.cc index 5d6cdd716006..8c40ab760f7f 100644 --- a/libstdc++-v3/testsuite/20_util/allocator_members.cc +++ b/libstdc++-v3/testsuite/20_util/allocator_members.cc @@ -1,6 +1,6 @@ // 2001-06-14 Benjamin Kosnik -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002 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 @@ -21,6 +21,7 @@ // 20.4.1.1 allocator members #include +#include #include #include @@ -42,7 +43,7 @@ void operator delete(void *v) throw() return std::free(v); } -int main(void) +void test01() { bool test = true; std::allocator obj; @@ -55,6 +56,34 @@ int main(void) obj.deallocate(pobj, 256); VERIFY( check_delete ); +} + +// libstdc++/8230 +void test02() +{ + bool test = true; + try + { + std::allocator alloc; + const std::allocator::size_type n = alloc.max_size(); + int* p = alloc.allocate(n + 1); + p[n] = 2002; + } + catch(const std::bad_alloc& e) + { + // Allowed. + test = true; + } + catch(...) + { + test = false; + } + VERIFY( test ); +} +int main() +{ + test01(); + test02(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/capacity.cc b/libstdc++-v3/testsuite/21_strings/capacity.cc index 6ffaa06f9e44..8473909103b1 100644 --- a/libstdc++-v3/testsuite/21_strings/capacity.cc +++ b/libstdc++-v3/testsuite/21_strings/capacity.cc @@ -209,7 +209,7 @@ void test01() sz02 = str011.length(); VERIFY( sz02 > sz01 ); - // trickster allocator (__USE_MALLOC, luke) issues involved with these: + // trickster allocator issues involved with these: std::string str3 = "8-chars_8-chars_"; const char* p3 = str3.c_str(); std::string str4 = str3 + "7-chars"; diff --git a/libstdc++-v3/testsuite/23_containers/vector_capacity.cc b/libstdc++-v3/testsuite/23_containers/vector_capacity.cc index e73b15a32468..8e9b6a8b1ab2 100644 --- a/libstdc++-v3/testsuite/23_containers/vector_capacity.cc +++ b/libstdc++-v3/testsuite/23_containers/vector_capacity.cc @@ -99,9 +99,30 @@ void test02() } } +void test03() +{ + bool test = true; + std::vector v; + try + { + v.resize(v.max_size()); + v[v.max_size() - 1] = 2002; + } + catch (const std::bad_alloc& error) + { + test = true; + } + catch (...) + { + test = false; + } + VERIFY( test ); +} + int main() { test01(); test02(); + test03(); return 0; } diff --git a/libstdc++-v3/testsuite/abi_check.cc b/libstdc++-v3/testsuite/abi_check.cc index c093cd507a6a..e956090e7098 100644 --- a/libstdc++-v3/testsuite/abi_check.cc +++ b/libstdc++-v3/testsuite/abi_check.cc @@ -134,7 +134,7 @@ const char* demangle(const std::string& mangled) { const char* name; - if (mangled[0] != '_' && mangled[1] != 'Z') + if (mangled[0] != '_' || mangled[1] != 'Z') { // This is not a mangled symbol, thus has "C" linkage. name = mangled.c_str(); @@ -365,6 +365,8 @@ main(int argc, char** argv) { vector compatible_versions; compatible_versions.push_back("GLIBCPP_3.2.1"); + compatible_versions.push_back("GLIBCPP_3.2.2"); + compatible_versions.push_back("CXXABI_1.2.1"); symbol_info test = test_symbols[added_names[i]]; vector::iterator end = compatible_versions.end(); diff --git a/libstdc++-v3/testsuite/ext/allocators.cc b/libstdc++-v3/testsuite/ext/allocators.cc index b3068e0b2ddf..99226255d5b5 100644 --- a/libstdc++-v3/testsuite/ext/allocators.cc +++ b/libstdc++-v3/testsuite/ext/allocators.cc @@ -1,6 +1,6 @@ // 2001-11-25 Phil Edwards // -// Copyright (C) 2001 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002 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,7 +20,6 @@ // 20.4.1.1 allocator members -#undef __USE_MALLOC #include #include #include @@ -75,7 +74,8 @@ void test() std::__allocator 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;