howto.html (GLIBCPP_FORCE_NEW): Document new environment variable which replaces...
authorLoren J. Rittle <ljrittle@acm.org>
Fri, 18 Oct 2002 20:52:57 +0000 (20:52 +0000)
committerLoren J. Rittle <ljrittle@gcc.gnu.org>
Fri, 18 Oct 2002 20:52:57 +0000 (20:52 +0000)
* 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

libstdc++-v3/ChangeLog
libstdc++-v3/docs/html/23_containers/howto.html
libstdc++-v3/docs/html/ext/howto.html
libstdc++-v3/include/backward/alloc.h
libstdc++-v3/include/bits/c++config
libstdc++-v3/include/bits/stl_alloc.h
libstdc++-v3/src/stl-inst.cc
libstdc++-v3/testsuite/21_strings/capacity.cc
libstdc++-v3/testsuite/ext/allocators.cc

index 7db0e574f121b8bc674399636717e467fc88bc37..4876e73d696e7f411dd011c97ec0c3acbfa19062 100644 (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
index 94226a21b7e62fcb5f57546ded609478442c2cab..008017a882757880a7dbd2c49ff263c3f6e659a0 100644 (file)
       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
index 2a038267627caf1490d66ccd30747059ae6c0030..007335b6569300111c5d1628413253f5e6ce99be 100644 (file)
          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
    </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:
-   </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>
+      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>
    <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;
index 4344a1d902c9a6ac7ea5e28686374c282c34158d..9482e4cfebad287bc793c34e6a81366a21b081af 100644 (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 
index 628e6c834e9abbaa06a7179bec773b159280c50c..05f2f5a0bfcba094e53a129013043cb7ead93794 100644 (file)
 // 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.
index c3b4b19b1769eaf2d1c548b1a260bea3547c3fb1..fceed498df6cafd08a0b8878756ed95b55965451 100644 (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;
-
-        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;
-      };
+       void* __ret = 0;
+
+       // 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;
-
-            // 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;
-          }
+       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;
+         }
       }
 
 #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
index d8879a7bccd82984378b4272e1dcc6d83b28354e..d80a718671847786b779475205ae5e7eb0571f04 100644 (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
index 3c45b0050170d11b465e0f24e8d7df4169c221b0..99a5b655f588d424874b68b107dea7f9a7943653 100644 (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";
index b3068e0b2ddf2880f8594336e3498692c65bd5f8..58152145e7e8483ab35308f291b18f2dc911e6fe 100644 (file)
@@ -20,7 +20,6 @@
 
 // 20.4.1.1 allocator members
 
-#undef __USE_MALLOC
 #include <memory>
 #include <cstdlib>
 #include <testsuite_hooks.h>