Commit 0b564d90 by Loren J. Rittle Committed by Loren J. Rittle

howto.html (GLIBCPP_FORCE_NEW): Document new environment variable which replaces…

howto.html (GLIBCPP_FORCE_NEW): Document new environment variable which replaces all uses of __USE_MALLOC macro.

	* 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: r58286
parent d3f76a70
2002-10-18 Loren J. Rittle <ljrittle@acm.org>
Brad Spencer <spencer@infointeractive.com> (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 <pme@gcc.gnu.org> 2002-10-18 Phil Edwards <pme@gcc.gnu.org>
* configure.in: Use target, not target_alias, when matching triplet * configure.in: Use target, not target_alias, when matching triplet
......
...@@ -251,41 +251,11 @@ ...@@ -251,41 +251,11 @@
solution would probably be more trouble than it's worth. solution would probably be more trouble than it's worth.
</p> </p>
<p>The STL implementation is currently configured to use the <p>The STL implementation is currently configured to use the
high-speed caching memory allocator. If you absolutely think high-speed caching memory allocator. Some people like to
you must change this on a global basis for your platform to better test and/or normally run threaded programs with a different
support multi-threading, then please consult all commentary in default. For all details about how to globally override this
include/bits/stl_alloc.h and the allocators link below. at application run-time see <a href="../ext/howto.html#3">here</a>.
</p> </p>
<blockquote>
<p>(Explicit warning since so many people get confused while
attempting this:)
</p>
<p><strong>Adding -D__USE_MALLOC on the command
line is almost certainly a bad idea.</strong> Memory efficiency is
almost guaranteed to suffer as a result; this is
<a href="http://gcc.gnu.org/ml/libstdc++/2001-05/msg00136.html">why
we disabled it for 3.0 in the first place</a>.
</p>
<p>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.
</p>
</blockquote>
<p>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.
</p>
<p>There is a better way (not standardized yet): It is possible to <p>There is a better way (not standardized yet): It is possible to
force the malloc-based allocator on a per-case-basis for some force the malloc-based allocator on a per-case-basis for some
application code. The library team generally believes that this application code. The library team generally believes that this
......
...@@ -280,19 +280,16 @@ ...@@ -280,19 +280,16 @@
same as <code>allocator&lt;T&gt;</code>. same as <code>allocator&lt;T&gt;</code>.
</li> </li>
</ul> </ul>
<p>An internal typedef, <code> __mem_interface </code>, is defined to be
<code>__new_alloc</code> by default.
</p>
<p>Normally, <p>Normally,
<code> __default_alloc_template&lt;bool thr, int inst&gt; </code> <code> __default_alloc_template&lt;bool thr, int inst&gt; </code>
is also available. This is the high-speed pool, called the default is also available. This is the high-speed pool, called the default
node allocator. The reusable memory is shared among identical node allocator. The reusable memory is shared among identical
instantiations of instantiations of
this type. It calls through <code>__mem_interface</code> to obtain this type. It calls through <code>__new_alloc</code> to obtain
new memory when its lists run out. If a client container requests a 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, block larger than a certain threshold size, then the pool is bypassed,
and the allocate/deallocate request is passed to and the allocate/deallocate request is passed to
<code>__mem_interface</code> directly. <code>__new_alloc</code> directly.
</p> </p>
<p>Its <code>inst</code> parameter is described below. The <p>Its <code>inst</code> parameter is described below. The
<code>thr</code> boolean determines whether the pool should be <code>thr</code> boolean determines whether the pool should be
...@@ -313,17 +310,25 @@ ...@@ -313,17 +310,25 @@
</p> </p>
<h3>A cannon to swat a fly:<code> __USE_MALLOC</code></h3> <h3>A cannon to swat a fly:<code> __USE_MALLOC</code></h3>
<p>If you've already read <a href="../23_containers/howto.html#3">this <p>If you've already read <a href="../23_containers/howto.html#3">this
advice</a> and decided to define this macro, then the situation changes advice</a> but still think you remember how to use this macro from
thusly: SGI STL days. We have removed it in gcc 3.3. See next section
</p> for the new way to get the same effect.
<ol> </p>
<li><code>__mem_interface</code>, and</li> <h3>Globally disabling memory caching:<code> GLIBCPP_FORCE_NEW</code></h3>
<li><code>__alloc</code>, and</li> <p>Starting with gcc 3.3, if you want to globally disable memory
<li><code>__single_client_alloc</code> are all typedef'd to caching within the library for the default allocator (i.e.
<code>__malloc_alloc_template</code>.</li> the one you get for all library objects when you do not specify
<li><code>__default_alloc_template</code> is no longer available. which one to use), merely set GLIBCPP_FORCE_NEW (at this time,
At all. Anywhere.</li> with any value) into your environment before running the
</ol> 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.
</p>
<h3>Writing your own allocators</h3> <h3>Writing your own allocators</h3>
<p>Depending on your application (a specific program, a generic library, <p>Depending on your application (a specific program, a generic library,
etc), allocator classes tend to be one of two styles: &quot;SGI&quot; etc), allocator classes tend to be one of two styles: &quot;SGI&quot;
......
...@@ -53,10 +53,6 @@ using std::__debug_alloc; ...@@ -53,10 +53,6 @@ using std::__debug_alloc;
using std::__alloc; using std::__alloc;
using std::__single_client_alloc; using std::__single_client_alloc;
using std::allocator; using std::allocator;
#ifdef __USE_MALLOC
using std::malloc_alloc;
#else
using std::__default_alloc_template; using std::__default_alloc_template;
#endif
#endif #endif
...@@ -74,13 +74,8 @@ ...@@ -74,13 +74,8 @@
// so, please report any possible issues to libstdc++@gcc.gnu.org . // so, please report any possible issues to libstdc++@gcc.gnu.org .
// Do not define __USE_MALLOC on the command line. Enforce it here: // Do not define __USE_MALLOC on the command line. Enforce it here:
#ifdef __USE_MALLOC #ifdef __USE_MALLOC
#error __USE_MALLOC should only be defined within \ #error __USE_MALLOC should never be defined. Read the release notes.
libstdc++-v3/include/bits/c++config before full recompilation of the library.
#endif #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 // The remainder of the prewritten config is mostly automatic; all the
// user hooks are listed above. // user hooks are listed above.
......
...@@ -89,6 +89,8 @@ ...@@ -89,6 +89,8 @@
#include <bits/functexcept.h> // For __throw_bad_alloc #include <bits/functexcept.h> // For __throw_bad_alloc
#include <bits/stl_threads.h> #include <bits/stl_threads.h>
#include <bits/atomicity.h>
namespace std namespace std
{ {
/** /**
...@@ -210,14 +212,8 @@ namespace std ...@@ -210,14 +212,8 @@ namespace std
} }
#endif #endif
// Should not be referenced within the library anymore.
// Determines the underlying allocator choice for the node allocator.
#ifdef __USE_MALLOC
typedef __malloc_alloc_template<0> __mem_interface;
#else
typedef __new_alloc __mem_interface; typedef __new_alloc __mem_interface;
#endif
/** /**
* @if maint * @if maint
...@@ -307,23 +303,16 @@ namespace std ...@@ -307,23 +303,16 @@ namespace std
}; };
#ifdef __USE_MALLOC
typedef __mem_interface __alloc;
typedef __mem_interface __single_client_alloc;
#else
/** /**
* @if maint * @if maint
* Default node allocator. "SGI" style. Uses __mem_interface for its * Default node allocator. "SGI" style. Uses various allocators to
* underlying requests (and makes as few requests as possible). * fulfill underlying requests (and makes as few requests as possible
* **** Currently __mem_interface is always __new_alloc, never __malloc*. * when in default high-speed pool mode).
* *
* Important implementation properties: * 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 * 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 * 2. In all other cases, we allocate an object of size exactly
* _S_round_up(requested_size). Thus the client has enough size * _S_round_up(requested_size). Thus the client has enough size
* information that we can return the object to the proper free list * information that we can return the object to the proper free list
...@@ -394,54 +383,69 @@ namespace std ...@@ -394,54 +383,69 @@ namespace std
} __attribute__ ((__unused__)); } __attribute__ ((__unused__));
friend struct _Lock; friend struct _Lock;
static _Atomic_word _S_force_new;
public: public:
// __n must be > 0 // __n must be > 0
static void* static void*
allocate(size_t __n) allocate(size_t __n)
{ {
void* __ret = 0; void* __ret = 0;
if (__n > (size_t) _MAX_BYTES) // If there is a race through here, assume answer from getenv
__ret = __mem_interface::allocate(__n); // will resolve in same direction. Inspired by techniques
else // to efficiently support threading found in basic_string.h.
{ if (_S_force_new == 0)
_Obj* volatile* __my_free_list = _S_free_list {
+ _S_freelist_index(__n); if (getenv("GLIBCPP_FORCE_NEW"))
// Acquire the lock here with a constructor call. This __atomic_add(&_S_force_new, 1);
// ensures that it is released in exit or during stack else
// unwinding. __atomic_add(&_S_force_new, -1);
_Lock __lock_instance; // Trust but verify...
_Obj* __restrict__ __result = *__my_free_list; assert (_S_force_new != 0);
if (__result == 0) }
__ret = _S_refill(_S_round_up(__n));
else if ((__n > (size_t) _MAX_BYTES) || (_S_force_new > 0))
{ __ret = __new_alloc::allocate(__n);
*__my_free_list = __result -> _M_free_list_link; else
__ret = __result; {
} _Obj* volatile* __my_free_list = _S_free_list
} + _S_freelist_index(__n);
return __ret; // 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 // __p may not be 0
static void static void
deallocate(void* __p, size_t __n) deallocate(void* __p, size_t __n)
{ {
if (__n > (size_t) _MAX_BYTES) if ((__n > (size_t) _MAX_BYTES) || (_S_force_new > 0))
__mem_interface::deallocate(__p, __n); __new_alloc::deallocate(__p, __n);
else else
{ {
_Obj* volatile* __my_free_list = _S_free_list _Obj* volatile* __my_free_list = _S_free_list
+ _S_freelist_index(__n); + _S_freelist_index(__n);
_Obj* __q = (_Obj*)__p; _Obj* __q = (_Obj*)__p;
// Acquire the lock here with a constructor call. This // Acquire the lock here with a constructor call. This
// ensures that it is released in exit or during stack // ensures that it is released in exit or during stack
// unwinding. // unwinding.
_Lock __lock_instance; _Lock __lock_instance;
__q -> _M_free_list_link = *__my_free_list; __q -> _M_free_list_link = *__my_free_list;
*__my_free_list = __q; *__my_free_list = __q;
} }
} }
#ifdef _GLIBCPP_DEPRECATED #ifdef _GLIBCPP_DEPRECATED
...@@ -450,6 +454,8 @@ namespace std ...@@ -450,6 +454,8 @@ namespace std
#endif #endif
}; };
template<bool __threads, int __inst> _Atomic_word
__default_alloc_template<__threads, __inst>::_S_force_new = 0;
template<bool __threads, int __inst> template<bool __threads, int __inst>
inline bool inline bool
...@@ -465,8 +471,8 @@ namespace std ...@@ -465,8 +471,8 @@ namespace std
// We allocate memory in large chunks in order to avoid fragmenting the // We allocate memory in large chunks in order to avoid fragmenting the
// malloc heap (or whatever __mem_interface is using) too much. We assume // heap too much. We assume that __size is properly aligned. We hold
// that __size is properly aligned. We hold the allocation lock. // the allocation lock.
template<bool __threads, int __inst> template<bool __threads, int __inst>
char* char*
__default_alloc_template<__threads, __inst>:: __default_alloc_template<__threads, __inst>::
...@@ -503,7 +509,7 @@ namespace std ...@@ -503,7 +509,7 @@ namespace std
((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list; ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
*__my_free_list = (_Obj*)_S_start_free; *__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) if (0 == _S_start_free)
{ {
size_t __i; size_t __i;
...@@ -528,7 +534,7 @@ namespace std ...@@ -528,7 +534,7 @@ namespace std
} }
} }
_S_end_free = 0; // In case of exception. _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. // This should either throw an exception or remedy the situation.
// Thus we assume it succeeded. // Thus we assume it succeeded.
} }
...@@ -618,7 +624,6 @@ namespace std ...@@ -618,7 +624,6 @@ namespace std
typedef __default_alloc_template<true,0> __alloc; typedef __default_alloc_template<true,0> __alloc;
typedef __default_alloc_template<false,0> __single_client_alloc; typedef __default_alloc_template<false,0> __single_client_alloc;
#endif /* ! __USE_MALLOC */
/** /**
...@@ -628,10 +633,6 @@ namespace std ...@@ -628,10 +633,6 @@ namespace std
* of stl_alloc.h.) * of stl_alloc.h.)
* *
* The underlying allocator behaves as follows. * 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 * - __default_alloc_template is used via two typedefs
* - "__single_client_alloc" typedef does no locking for threads * - "__single_client_alloc" typedef does no locking for threads
* - "__alloc" typedef is threadsafe via the locks * - "__alloc" typedef is threadsafe via the locks
...@@ -908,7 +909,6 @@ namespace std ...@@ -908,7 +909,6 @@ namespace std
typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
}; };
#ifndef __USE_MALLOC
template<typename _Tp, bool __threads, int __inst> template<typename _Tp, bool __threads, int __inst>
struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> > struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> >
{ {
...@@ -918,7 +918,6 @@ namespace std ...@@ -918,7 +918,6 @@ namespace std
typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> > typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> >
allocator_type; allocator_type;
}; };
#endif
template<typename _Tp, typename _Alloc> template<typename _Tp, typename _Alloc>
struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> > struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> >
...@@ -941,7 +940,6 @@ namespace std ...@@ -941,7 +940,6 @@ namespace std
typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type; typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
}; };
#ifndef __USE_MALLOC
template<typename _Tp, typename _Tp1, bool __thr, int __inst> template<typename _Tp, typename _Tp1, bool __thr, int __inst>
struct _Alloc_traits<_Tp, __allocator<_Tp1, __default_alloc_template<__thr, __inst> > > struct _Alloc_traits<_Tp, __allocator<_Tp1, __default_alloc_template<__thr, __inst> > >
{ {
...@@ -951,7 +949,6 @@ namespace std ...@@ -951,7 +949,6 @@ namespace std
typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> > typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> >
allocator_type; allocator_type;
}; };
#endif
template<typename _Tp, typename _Tp1, typename _Alloc> template<typename _Tp, typename _Tp1, typename _Alloc>
struct _Alloc_traits<_Tp, __allocator<_Tp1, __debug_alloc<_Alloc> > > struct _Alloc_traits<_Tp, __allocator<_Tp1, __debug_alloc<_Alloc> > >
...@@ -967,11 +964,7 @@ namespace std ...@@ -967,11 +964,7 @@ namespace std
// NB: This syntax is a GNU extension. // NB: This syntax is a GNU extension.
extern template class allocator<char>; extern template class allocator<char>;
extern template class allocator<wchar_t>; extern template class allocator<wchar_t>;
#ifdef __USE_MALLOC
extern template class __malloc_alloc_template<0>;
#else
extern template class __default_alloc_template<true,0>; extern template class __default_alloc_template<true,0>;
#endif
} // namespace std } // namespace std
#endif #endif
...@@ -39,9 +39,5 @@ namespace std ...@@ -39,9 +39,5 @@ namespace std
template class allocator<char>; template class allocator<char>;
template class allocator<wchar_t>; template class allocator<wchar_t>;
#ifdef __USE_MALLOC
template class __malloc_alloc_template<0>;
#else
template class __default_alloc_template<true, 0>; template class __default_alloc_template<true, 0>;
#endif
} // namespace std } // namespace std
...@@ -209,7 +209,7 @@ void test01() ...@@ -209,7 +209,7 @@ void test01()
sz02 = str011.length(); sz02 = str011.length();
VERIFY( sz02 > sz01 ); 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_"; std::string str3 = "8-chars_8-chars_";
const char* p3 = str3.c_str(); const char* p3 = str3.c_str();
std::string str4 = str3 + "7-chars"; std::string str4 = str3 + "7-chars";
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
// 20.4.1.1 allocator members // 20.4.1.1 allocator members
#undef __USE_MALLOC
#include <memory> #include <memory>
#include <cstdlib> #include <cstdlib>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment