diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7db0e574f12..4876e73d696 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,30 @@ +2002-10-18 Loren J. Rittle + Brad Spencer (provided alternate + patch and improvements) + + * 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-10-18 Phil Edwards * configure.in: Use target, not target_alias, when matching triplet diff --git a/libstdc++-v3/docs/html/23_containers/howto.html b/libstdc++-v3/docs/html/23_containers/howto.html index 94226a21b7e..008017a8827 100644 --- a/libstdc++-v3/docs/html/23_containers/howto.html +++ b/libstdc++-v3/docs/html/23_containers/howto.html @@ -251,41 +251,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 2a038267627..007335b6569 100644 --- a/libstdc++-v3/docs/html/ext/howto.html +++ b/libstdc++-v3/docs/html/ext/howto.html @@ -280,19 +280,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 @@ -313,17 +310,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: + 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.

-
    -
  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. -

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 4344a1d902c..9482e4cfeba 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 628e6c834e9..05f2f5a0bfc 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 c3b4b19b176..fceed498df6 100644 --- a/libstdc++-v3/include/bits/stl_alloc.h +++ b/libstdc++-v3/include/bits/stl_alloc.h @@ -89,6 +89,8 @@ #include // For __throw_bad_alloc #include +#include + namespace std { /** @@ -210,14 +212,8 @@ namespace std } #endif - - // 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 @@ -307,23 +303,16 @@ namespace std }; -#ifdef __USE_MALLOC - - typedef __mem_interface __alloc; - typedef __mem_interface __single_client_alloc; - -#else - - /** * @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*. + * 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 the underlying __mem_interface. + * 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 @@ -394,54 +383,69 @@ namespace std } __attribute__ ((__unused__)); friend struct _Lock; + static _Atomic_word _S_force_new; + public: // __n must be > 0 static void* allocate(size_t __n) { - void* __ret = 0; + 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; - }; + // 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 (__result == 0) + __ret = _S_refill(_S_round_up(__n)); + else + { + *__my_free_list = __result -> _M_free_list_link; + __ret = __result; + } + } + 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; + 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; - } + // 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; + } } #ifdef _GLIBCPP_DEPRECATED @@ -450,6 +454,8 @@ namespace std #endif }; + template _Atomic_word + __default_alloc_template<__threads, __inst>::_S_force_new = 0; template inline bool @@ -465,8 +471,8 @@ namespace std // 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>:: @@ -503,7 +509,7 @@ namespace std ((_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); + _S_start_free = (char*) __new_alloc::allocate(__bytes_to_get); if (0 == _S_start_free) { size_t __i; @@ -528,7 +534,7 @@ namespace std } } _S_end_free = 0; // In case of exception. - _S_start_free = (char*)__mem_interface::allocate(__bytes_to_get); + _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. } @@ -618,7 +624,6 @@ namespace std typedef __default_alloc_template __alloc; typedef __default_alloc_template __single_client_alloc; -#endif /* ! __USE_MALLOC */ /** @@ -628,10 +633,6 @@ namespace std * 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 @@ -908,7 +909,6 @@ namespace std typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; }; -#ifndef __USE_MALLOC template struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> > { @@ -918,7 +918,6 @@ namespace std typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> > allocator_type; }; -#endif template struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> > @@ -941,7 +940,6 @@ namespace std typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; }; -#ifndef __USE_MALLOC template struct _Alloc_traits<_Tp, __allocator<_Tp1, __default_alloc_template<__thr, __inst> > > { @@ -951,7 +949,6 @@ namespace std typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> > allocator_type; }; -#endif template struct _Alloc_traits<_Tp, __allocator<_Tp1, __debug_alloc<_Alloc> > > @@ -967,11 +964,7 @@ namespace std // 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 } // namespace std #endif diff --git a/libstdc++-v3/src/stl-inst.cc b/libstdc++-v3/src/stl-inst.cc index d8879a7bccd..d80a7186718 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/21_strings/capacity.cc b/libstdc++-v3/testsuite/21_strings/capacity.cc index 3c45b005017..99a5b655f58 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/ext/allocators.cc b/libstdc++-v3/testsuite/ext/allocators.cc index b3068e0b2dd..58152145e7e 100644 --- a/libstdc++-v3/testsuite/ext/allocators.cc +++ b/libstdc++-v3/testsuite/ext/allocators.cc @@ -20,7 +20,6 @@ // 20.4.1.1 allocator members -#undef __USE_MALLOC #include #include #include