[PATCH] Slightly better way to __USE_MALLOC
Brad Spencer
spencer@infointeractive.com
Thu Oct 17 07:43:00 GMT 2002
On Wed, Oct 16, 2002 at 10:37:37PM -0500, Benjamin Kosnik wrote:
>
> So is this patch finished, and ready to review?
Yes. Sorry about the delay, but other work has caught up to me. I
don't know if I'll say it's finished because I'm not sure I can meet
everyone's wishes ;)
Completed:
Renamed __default_alloc_template to __pool_alloc_template.
Made the definitions of both allocation templates present in the
library, and _GLIBCPP_USE_MALLOC just selects which is the default one
used by std::allocator.
Added (naive?) link-time guards to prevent objects compiled with
different _GLIBCPP_USE_MALLOC settings from linking. Tips on how to
do this with symbol versioning would be appreciated.
TODO:
Figure out what the comment in c++config.h should say.
Write the final configopts.html entry and FAQ entry.
I hate to submit this patch in this semi-finalized form (I don't like
to be sloppy), but it's probably better than letting it rot. I
haven't had the opportunity to run the test suite on it yet either.
I will be able to work more on it now if there are suggestions.
--
------------------------------------------------------------------
Brad Spencer - spencer@infointeractive.com - "It's quite nice..."
Systems Architect | InfoInterActive Corp. | A Canadian AOL Company
-------------- next part --------------
Index: acconfig.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/acconfig.h,v
retrieving revision 1.25
diff -u -p -r1.25 acconfig.h
--- acconfig.h 14 Dec 2001 21:06:32 -0000 1.25
+++ acconfig.h 11 Oct 2002 00:59:36 -0000
@@ -37,6 +37,9 @@
// Define to use concept checking code from the boost libraries.
#undef _GLIBCPP_CONCEPT_CHECKS
+// Define to use the malloc-based allocator instead pool-based one
+#undef _GLIBCPP_USE_MALLOC
+
// Define if you have the atan2f function.
#undef _GLIBCPP_HAVE_ATAN2F
Index: acinclude.m4
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/acinclude.m4,v
retrieving revision 1.220
diff -u -p -r1.220 acinclude.m4
--- acinclude.m4 17 Sep 2002 05:50:31 -0000 1.220
+++ acinclude.m4 11 Oct 2002 00:59:36 -0000
@@ -2106,6 +2106,38 @@ fi
dnl
+dnl Check for whether the _GLIBCPP_USE_MALLOC macro should be defined and thus
+dnl whether the library should be built with the malloc-based allocator
+dnl underneath the STL containers instead of the pool-based allocator.
+dnl
+dnl GLIBCPP_ENABLE_POOL_ALLOCATOR
+dnl --enable-pool-allocator enables the pool-based allocator.
+dnl --disable-pool-allocator turns it off off.
+dnl + Usage: GLIBCPP_ENABLE_USE_MALLOC[(DEFAULT)]
+dnl Where DEFAULT is either `yes' or `no'. If ommitted, it
+dnl defaults to `yes'.
+AC_DEFUN(GLIBCPP_ENABLE_POOL_ALLOCATOR, [dnl
+define([GLIBCPP_ENABLE_POOL_ALLOCATOR_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(pool-allocator,
+changequote(<<, >>)dnl
+<< --enable-pool-allocator use the fast pool-based allocator [default=>>GLIBCPP_ENABLE_POOL_ALLOCATOR_DEFAULT],
+changequote([, ])dnl
+[case "$enableval" in
+ yes) enable_pool_allocator=yes ;;
+ no) enable_pool_allocator=no ;;
+ *) AC_MSG_ERROR([Unknown argument to enable/disable pool allocator]) ;;
+ esac],
+enable_pool_allocator=GLIBCPP_ENABLE_POOL_ALLOCATOR_DEFAULT)dnl
+dnl Option parsed, now set things appropriately
+AC_MSG_CHECKING([whether to use pool allocator])
+if test x"$enable_pool_allocator" = xno; then
+ AC_DEFINE(_GLIBCPP_USE_MALLOC)
+fi
+AC_MSG_RESULT($enable_pool_allocator)
+])
+
+
+dnl
dnl Add version tags to symbols in shared library (or not), additionally
dnl marking other symbols as private/local (or not).
dnl
Index: config.h.in
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/config.h.in,v
retrieving revision 1.56
diff -u -p -r1.56 config.h.in
--- config.h.in 11 Jun 2002 17:53:59 -0000 1.56
+++ config.h.in 11 Oct 2002 00:59:37 -0000
@@ -24,6 +24,9 @@
// Define to use concept checking code from the boost libraries.
#undef _GLIBCPP_CONCEPT_CHECKS
+// Define to use the malloc-based allocator instead pool-based one
+#undef _GLIBCPP_USE_MALLOC
+
// Define if mbstate_t exists in wchar.h.
#undef HAVE_MBSTATE_T
Index: configure.in
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/configure.in,v
retrieving revision 1.105
diff -u -p -r1.105 configure.in
--- configure.in 26 Sep 2002 05:25:05 -0000 1.105
+++ configure.in 11 Oct 2002 00:59:37 -0000
@@ -66,6 +66,7 @@ GLIBCPP_ENABLE_CXX_FLAGS([none])
GLIBCPP_ENABLE_SJLJ_EXCEPTIONS
GLIBCPP_ENABLE_LIBUNWIND_EXCEPTIONS
GLIBCPP_ENABLE_CONCEPT_CHECKS
+GLIBCPP_ENABLE_POOL_ALLOCATOR
# Check for headers necessary for libsupc++ using dyn-string.c/cxa_demangle.c
AC_CHECK_HEADERS(string.h stdlib.h)
Index: include//backward/alloc.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/backward/alloc.h,v
retrieving revision 1.11
diff -u -p -r1.11 alloc.h
--- include//backward/alloc.h 6 Dec 2001 20:29:30 -0000 1.11
+++ include//backward/alloc.h 11 Oct 2002 00:59:37 -0000
@@ -50,13 +50,9 @@
using std::__malloc_alloc_template;
using std::__simple_alloc;
using std::__debug_alloc;
+using std::__pool_alloc_template;
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
Index: include//bits/c++config
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/c++config,v
retrieving revision 1.505
diff -u -p -r1.505 c++config
--- include//bits/c++config 7 Oct 2002 07:19:04 -0000 1.505
+++ include//bits/c++config 11 Oct 2002 00:59:37 -0000
@@ -69,15 +69,19 @@
// that threads are properly configured on your platform before
// assigning blame to the STL container-memory allocator. After doing
// 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.
-#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.
+//
+// TODO: XXX Fix this comment!
+// Do not arbitrarily define _GLIBCPP_USE_MALLOC on the command line.
+// It must be defined at library-build time (via the
+// --enable-pool-allocator option). Configure the library to use
+// malloc (via --enable-pool-allocator=no) in order to aid debugging or
+// globally change allocation policy. This breaks the ABI, thus
+// completely recompile the library.
+//
+// See libstdc++-v3/docs/html/configopts.html for details.
+//
+// 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.
Index: include//bits/stl_alloc.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/stl_alloc.h,v
retrieving revision 1.24
diff -u -p -r1.24 stl_alloc.h
--- include//bits/stl_alloc.h 23 Aug 2002 16:52:29 -0000 1.24
+++ include//bits/stl_alloc.h 11 Oct 2002 00:59:38 -0000
@@ -115,9 +115,9 @@ namespace std
/**
* @if maint
* A malloc-based allocator. Typically slower than the
- * __default_alloc_template (below). Typically thread-safe and more
+ * __pool_alloc_template (below). Typically thread-safe and more
* storage efficient. The template argument is unused and is only present
- * to permit multiple instantiations (but see __default_alloc_template
+ * to permit multiple instantiations (but see __pool_alloc_template
* for caveats). "SGI" style, plus __set_malloc_handler for OOM conditions.
* @endif
* (See @link Allocators allocators info @endlink for more.)
@@ -211,8 +211,11 @@ namespace std
#endif
- // Determines the underlying allocator choice for the node allocator.
-#ifdef __USE_MALLOC
+ // Determines the underlying allocator choice for the node allocator. The
+ // standard requires new and delete, but we allow raw malloc and free when
+ // the malloc allocator is in use. This can (probably) change the ABI.
+ // TODO: XXX Is this wise?
+#ifdef _GLIBCPP_USE_MALLOC
typedef __malloc_alloc_template<0> __mem_interface;
#else
typedef __new_alloc __mem_interface;
@@ -306,15 +309,6 @@ namespace std
#endif
};
-
-#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
@@ -331,21 +325,21 @@ namespace std
*
* 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
+ * of a pool_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
+ * multiple pool_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.
+ * pool_alloc instance, instantiate this with a non-zero __inst.
*
* @endif
* (See @link Allocators allocators info @endlink for more.)
*/
template<bool __threads, int __inst>
- class __default_alloc_template
+ class __pool_alloc_template
{
private:
enum {_ALIGN = 8};
@@ -453,14 +447,14 @@ namespace std
template<bool __threads, int __inst>
inline bool
- operator==(const __default_alloc_template<__threads,__inst>&,
- const __default_alloc_template<__threads,__inst>&)
+ operator==(const __pool_alloc_template<__threads,__inst>&,
+ const __pool_alloc_template<__threads,__inst>&)
{ return true; }
template<bool __threads, int __inst>
inline bool
- operator!=(const __default_alloc_template<__threads,__inst>&,
- const __default_alloc_template<__threads,__inst>&)
+ operator!=(const __pool_alloc_template<__threads,__inst>&,
+ const __pool_alloc_template<__threads,__inst>&)
{ return false; }
@@ -469,7 +463,7 @@ namespace std
// that __size is properly aligned. We hold the allocation lock.
template<bool __threads, int __inst>
char*
- __default_alloc_template<__threads, __inst>::
+ __pool_alloc_template<__threads, __inst>::
_S_chunk_alloc(size_t __size, int& __nobjs)
{
char* __result;
@@ -544,7 +538,7 @@ namespace std
// hold the allocation lock.
template<bool __threads, int __inst>
void*
- __default_alloc_template<__threads, __inst>::_S_refill(size_t __n)
+ __pool_alloc_template<__threads, __inst>::_S_refill(size_t __n)
{
int __nobjs = 20;
char* __chunk = _S_chunk_alloc(__n, __nobjs);
@@ -580,7 +574,7 @@ namespace std
#ifdef _GLIBCPP_DEPRECATED
template<bool threads, int inst>
void*
- __default_alloc_template<threads, inst>::
+ __pool_alloc_template<threads, inst>::
reallocate(void* __p, size_t __old_sz, size_t __new_sz)
{
void* __result;
@@ -600,25 +594,37 @@ namespace std
template<bool __threads, int __inst>
_STL_mutex_lock
- __default_alloc_template<__threads,__inst>::_S_node_allocator_lock
+ __pool_alloc_template<__threads,__inst>::_S_node_allocator_lock
__STL_MUTEX_INITIALIZER;
template<bool __threads, int __inst>
- char* __default_alloc_template<__threads,__inst>::_S_start_free = 0;
+ char* __pool_alloc_template<__threads,__inst>::_S_start_free = 0;
template<bool __threads, int __inst>
- char* __default_alloc_template<__threads,__inst>::_S_end_free = 0;
+ char* __pool_alloc_template<__threads,__inst>::_S_end_free = 0;
template<bool __threads, int __inst>
- size_t __default_alloc_template<__threads,__inst>::_S_heap_size = 0;
+ size_t __pool_alloc_template<__threads,__inst>::_S_heap_size = 0;
template<bool __threads, int __inst>
- typename __default_alloc_template<__threads,__inst>::_Obj* volatile
- __default_alloc_template<__threads,__inst>::_S_free_list[_NFREELISTS];
+ typename __pool_alloc_template<__threads,__inst>::_Obj* volatile
+ __pool_alloc_template<__threads,__inst>::_S_free_list[_NFREELISTS];
+
+ // Select the implementation of the standard std::allocator (hereafter
+ // referred to as the "default allocator"). This can change the ABI.
+#ifdef _GLIBCPP_USE_MALLOC
+
+ // Use the malloc-based allocator for all node allocations themselves
+ typedef __mem_interface __alloc;
+ typedef __mem_interface __single_client_alloc;
+
+#else /* _GLIBCPP_USE_MALLOC */
- typedef __default_alloc_template<true,0> __alloc;
- typedef __default_alloc_template<false,0> __single_client_alloc;
-#endif /* ! __USE_MALLOC */
+ // Use the pool-based allocator for all node allocations themselves
+ typedef __pool_alloc_template<true,0> __alloc;
+ typedef __pool_alloc_template<false,0> __single_client_alloc;
+
+#endif /* ! _GLIBCPP_USE_MALLOC */
/**
@@ -628,11 +634,11 @@ namespace std
* of stl_alloc.h.)
*
* The underlying allocator behaves as follows.
- * - if __USE_MALLOC then
+ * - if _GLIBCPP_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
+ * - __pool_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
@@ -908,17 +914,15 @@ 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> >
+ struct _Alloc_traits<_Tp, __pool_alloc_template<__threads, __inst> >
{
static const bool _S_instanceless = true;
- typedef __simple_alloc<_Tp, __default_alloc_template<__threads, __inst> >
+ typedef __simple_alloc<_Tp, __pool_alloc_template<__threads, __inst> >
_Alloc_type;
- typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> >
+ typedef __allocator<_Tp, __pool_alloc_template<__threads, __inst> >
allocator_type;
};
-#endif
template<typename _Tp, typename _Alloc>
struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> >
@@ -941,17 +945,15 @@ 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> > >
+ struct _Alloc_traits<_Tp, __allocator<_Tp1, __pool_alloc_template<__thr, __inst> > >
{
static const bool _S_instanceless = true;
- typedef __simple_alloc<_Tp, __default_alloc_template<__thr,__inst> >
+ typedef __simple_alloc<_Tp, __pool_alloc_template<__thr,__inst> >
_Alloc_type;
- typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> >
+ typedef __allocator<_Tp, __pool_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 +969,37 @@ namespace std
// NB: This syntax is a GNU extension.
extern template class allocator<char>;
extern template class allocator<wchar_t>;
-#ifdef __USE_MALLOC
+
+ // Both allocators are instantiated in the library itself regardless of
+ // which is the default node allocator.
extern template class __malloc_alloc_template<0>;
+ extern template class __pool_alloc_template<true,0>;
+
+ // Possible extension mentioned in
+ // http://gcc.gnu.org/ml/libstdc++/2002-10/msg00079.html
+ // Provides an easy way for the user to ask for either allocation mechanism
+ // regardless of the default. We pick the most efficient form that
+ // implements the desired mechanism.
+ // Another way
+#ifdef _GLIBCPP_USE_MALLOC
+ typedef allocator<void> __malloc_allocator;
+ typedef __allocator<void, __pool_alloc_template<true, 0> > __pool_allocator;
+#else /* _GLIBCPP_USE_MALLOC */
+ typedef __allocator<void, __malloc_alloc_template<0> > __malloc_allocator;
+ typedef allocator<void> __pool_allocator;
+#endif /* _GLIBCPP_USE_MALLOC */
+
+ // Prevent linkage of objects compiled with different default allocators
+#ifdef _GLIBCPP_USE_MALLOC
+ extern const int __default_allocator_is_malloc_alloc_template;
+ static const int* __default_allocator =
+ &__default_allocator_is_malloc_alloc_template;
#else
- extern template class __default_alloc_template<true,0>;
+ extern const int __default_allocator_is_pool_alloc_template;
+ static const int* __default_allocator =
+ &__default_allocator_is_pool_alloc_template;
#endif
+
} // namespace std
#endif
Index: testsuite//ext/allocators.cc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/testsuite/ext/allocators.cc,v
retrieving revision 1.1
diff -u -p -r1.1 allocators.cc
--- testsuite//ext/allocators.cc 11 Dec 2001 19:04:58 -0000 1.1
+++ testsuite//ext/allocators.cc 11 Oct 2002 00:59:39 -0000
@@ -20,7 +20,6 @@
// 20.4.1.1 allocator members
-#undef __USE_MALLOC
#include <memory>
#include <cstdlib>
#include <testsuite_hooks.h>
@@ -31,11 +30,11 @@ template class std::__malloc_alloc_templ
typedef std::__debug_alloc<weird_alloc> debug_weird_alloc;
template class std::__debug_alloc<weird_alloc>;
-typedef std::__default_alloc_template<true, 3> unshared_normal_alloc;
-template class std::__default_alloc_template<true, 3>;
+typedef std::__pool_alloc_template<true, 3> unshared_normal_alloc;
+template class std::__pool_alloc_template<true, 3>;
-typedef std::__default_alloc_template<false, 3> unshared_singlethreaded;
-template class std::__default_alloc_template<false, 3>;
+typedef std::__pool_alloc_template<false, 3> unshared_singlethreaded;
+template class std::__pool_alloc_template<false, 3>;
//std::malloc_alloc test_malloc_alloc;
More information about the Libstdc++
mailing list