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:
parent
d3f76a7098
commit
0b564d905f
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -280,19 +280,16 @@
|
|||
same as <code>allocator<T></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<bool thr, int inst> </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: "SGI"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
// 20.4.1.1 allocator members
|
||||
|
||||
#undef __USE_MALLOC
|
||||
#include <memory>
|
||||
#include <cstdlib>
|
||||
#include <testsuite_hooks.h>
|
||||
|
|
Loading…
Reference in New Issue