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
This commit is contained in:
Loren J. Rittle 2002-10-18 20:52:57 +00:00 committed by Loren J. Rittle
parent d3f76a7098
commit 0b564d905f
9 changed files with 118 additions and 137 deletions

View File

@ -1,3 +1,30 @@
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>
* configure.in: Use target, not target_alias, when matching triplet

View File

@ -251,41 +251,11 @@
solution would probably be more trouble than it's worth.
</p>
<p>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 <a href="../ext/howto.html#3">here</a>.
</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
force the malloc-based allocator on a per-case-basis for some
application code. The library team generally believes that this

View File

@ -280,19 +280,16 @@
same as <code>allocator&lt;T&gt;</code>.
</li>
</ul>
<p>An internal typedef, <code> __mem_interface </code>, is defined to be
<code>__new_alloc</code> by default.
</p>
<p>Normally,
<code> __default_alloc_template&lt;bool thr, int inst&gt; </code>
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 <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
block larger than a certain threshold size, then the pool is bypassed,
and the allocate/deallocate request is passed to
<code>__mem_interface</code> directly.
<code>__new_alloc</code> directly.
</p>
<p>Its <code>inst</code> parameter is described below. The
<code>thr</code> boolean determines whether the pool should be
@ -313,17 +310,25 @@
</p>
<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
advice</a> and decided to define this macro, then the situation changes
thusly:
advice</a> 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.
</p>
<h3>Globally disabling memory caching:<code> GLIBCPP_FORCE_NEW</code></h3>
<p>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.
</p>
<ol>
<li><code>__mem_interface</code>, and</li>
<li><code>__alloc</code>, and</li>
<li><code>__single_client_alloc</code> are all typedef'd to
<code>__malloc_alloc_template</code>.</li>
<li><code>__default_alloc_template</code> is no longer available.
At all. Anywhere.</li>
</ol>
<h3>Writing your own allocators</h3>
<p>Depending on your application (a specific program, a generic library,
etc), allocator classes tend to be one of two styles: &quot;SGI&quot;

View File

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

View File

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

View File

@ -89,6 +89,8 @@
#include <bits/functexcept.h> // For __throw_bad_alloc
#include <bits/stl_threads.h>
#include <bits/atomicity.h>
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<bool __threads, int __inst> _Atomic_word
__default_alloc_template<__threads, __inst>::_S_force_new = 0;
template<bool __threads, int __inst>
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<bool __threads, int __inst>
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<true,0> __alloc;
typedef __default_alloc_template<false,0> __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<typename _Tp, bool __threads, int __inst>
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<typename _Tp, typename _Alloc>
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<typename _Tp, typename _Tp1, bool __thr, int __inst>
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<typename _Tp, typename _Tp1, typename _Alloc>
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<char>;
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>;
#endif
} // namespace std
#endif

View File

@ -39,9 +39,5 @@ namespace std
template class allocator<char>;
template class allocator<wchar_t>;
#ifdef __USE_MALLOC
template class __malloc_alloc_template<0>;
#else
template class __default_alloc_template<true, 0>;
#endif
} // namespace std

View File

@ -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";

View File

@ -20,7 +20,6 @@
// 20.4.1.1 allocator members
#undef __USE_MALLOC
#include <memory>
#include <cstdlib>
#include <testsuite_hooks.h>