[v3] locale cache PR 7076,8761

Jerry Quinn jlquinn@optonline.net
Mon Jun 30 04:37:00 GMT 2003


This is another iteration of locale cache for the 3.3 branch.  It
doesn't achieve parity with 2.95, but cuts runtimes on the 8761
testcase in half.

2.95

real    0m3.828s
user    0m3.510s
sys     0m0.320s

3.3

real    0m11.422s
user    0m10.970s
sys     0m0.390s


3.3 + patch

real    0m5.046s
user    0m4.570s
sys     0m0.460s

Passes make check w/ no regressions, doesn't suffer from either PR
10276 or PR 9828.

The one concern I is make check-abi complains about the increase in
size of facet_vec.  I don't believe it's an issue, but wiser heads may
have a different opinion.

Jerry

2003-06-30  Benjamin Kosnik  <bkoz@redhat.com>
	    Jerry Quinn  <jlquinn@optonline.net>

	* include/bits/ios_base.h (ios_base::_M_getloc): Return reference
	to the imbued locale.

	* include/bits/locale_classes.h
	(__locale_cache_base,__locale_cache): Declare.
	(locale,locale::_Impl): Befriend __use_cache.
	(locale::_Impl::_M_get_cache): New function.
	(locale::_Impl::_M_install_cache): New function.
	* include/bits/locale_facets.h (__locale_cache): Declare.
	(numpunct): Befriend __locale_cache.
	(__locale_cache_base): New class.
	(__locale_cache): New class.
	* include/bits/locale_facets.tcc (__use_cache): New function.
	(num_put::_M_convert_int,_M_convert_float,do_put): Use it.
	Use cache data members in place of calls to facet.
	(num_put::_M_convert_int): Use _M_getloc.
	(num_put::_M_convert_float): Use _M_getloc.
	(__locale_cache::__locale_cache(locale&): New.
	(__locale_cache::__locale_cache(locale&,bool)): New.
	* src/globals.cc (facet_vec): Enlarge.
	(locale_cache_numpunct_c, locale_cache_numpunct_w): New.
	* src/locale-inst.cc
	(__locale_cache<numpunct<char> >): Define.
	(__locale_cache<numpunct<wchar_t> >): Define.
	(__use_cache<numpunct<char> >): Define.
	(__use_cache<numpunct<wchar_t> >): Define.
	* src/localename.cc (facet_vec): Update declaration.
	(locale_cache_numpunct_c, locale_cache_numpunct_w): Declare.
	(locale::_Impl::~Impl): Destroy caches.
	(locale::_Impl::Impl):  Initialize cache storage.  Fill in
	static caches.
	(__locale_cache::_M_id): Define.
	(__locale_cache_base::id::_S_highwater): Define.
	(__locale_cache_base::id::id): Define.


Index: include/bits/ios_base.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/ios_base.h,v
retrieving revision 1.21.2.6
diff -u -r1.21.2.6 ios_base.h
--- include/bits/ios_base.h	2 May 2003 01:08:04 -0000	1.21.2.6
+++ include/bits/ios_base.h	30 Jun 2003 04:00:53 -0000
@@ -604,7 +604,7 @@
 
     /**
      *  @brief  Locale access
-     *  @return  The locale currently in effect.
+     *  @return  A copy of the current locale.
      *
      *  If @c imbue(loc) has previously been called, then this function
      *  returns @c loc.  Otherwise, it returns a copy of @c std::locale(),
@@ -612,6 +612,16 @@
     */
     inline locale 
     getloc() const { return _M_ios_locale; }
+
+    /**
+     *  @brief  Locale access
+     *  @return  A reference to the current locale.
+     *
+     *  Like getloc above, but returns a reference instead of
+     *  generating a copy.
+    */
+    inline const locale& 
+    _M_getloc() const { return _M_ios_locale; }
 
     // [27.4.2.5] ios_base storage functions
     /**
Index: include/bits/locale_classes.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/locale_classes.h,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 locale_classes.h
--- include/bits/locale_classes.h	23 Jan 2003 18:56:17 -0000	1.1.2.2
+++ include/bits/locale_classes.h	30 Jun 2003 04:00:53 -0000
@@ -49,6 +49,9 @@
 
 namespace std
 {
+  class __locale_cache_base;
+  template<typename _Facet> class __locale_cache;
+
   // 22.1.1 Class locale
   class locale
   {
@@ -72,6 +75,10 @@
       friend bool 
       has_facet(const locale&) throw();
  
+    template<typename _Facet>
+      friend const __locale_cache<_Facet>&
+      __use_cache(const locale&);
+
     // Category values:
     // NB: Order must match _S_facet_categories definition in locale.cc
     static const category none		= 0;
@@ -196,6 +203,10 @@
       friend bool  
       has_facet(const locale&) throw();
 
+    template<typename _Facet>
+      friend const __locale_cache<_Facet>&
+      __use_cache(const locale&);
+
   private:
     // Data Members.
     _Atomic_word			_M_references;
@@ -266,6 +277,25 @@
       inline void 
       _M_init_facet(_Facet* __facet)
       { _M_install_facet(&_Facet::id, __facet);  }
+
+    // Retrieve the cache at __index.  0 is returned if the cache is
+    // missing.  Cache is actually located at __index +
+    // _M_facets_size.  __index must be < _M_facets_size.
+    inline __locale_cache_base*
+      _M_get_cache(size_t __index)
+      {
+	return (__locale_cache_base*)_M_facets[__index + _M_facets_size];
+      }
+
+    // Save the supplied cache at __id.  Assumes _M_get_cache has been
+    // called.
+    void
+    _M_install_cache(__locale_cache_base* __cache, int __id)
+    {
+      _M_facets[__id + _M_facets_size] = 
+	reinterpret_cast<locale::facet*>(__cache);
+    }
+      
   };
 
   template<typename _Facet>
Index: include/bits/locale_facets.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/locale_facets.h,v
retrieving revision 1.49.4.7
diff -u -r1.49.4.7 locale_facets.h
--- include/bits/locale_facets.h	2 May 2003 01:08:04 -0000	1.49.4.7
+++ include/bits/locale_facets.h	30 Jun 2003 04:00:53 -0000
@@ -581,6 +581,9 @@
 
 
   template<typename _CharT>
+    class __locale_cache;
+
+  template<typename _CharT>
     class numpunct : public locale::facet
     {
     public:
@@ -588,6 +591,8 @@
       typedef _CharT          		char_type;
       typedef basic_string<_CharT> 	string_type;
 
+      friend class __locale_cache<numpunct<_CharT> >;
+
       static locale::id 		id;
 
     private:
@@ -1953,6 +1958,89 @@
     inline _CharT 
     tolower(_CharT __c, const locale& __loc)
     { return use_facet<ctype<_CharT> >(__loc).tolower(__c); }
+
+  // __locale_cache objects hold information extracted from facets in
+  // a form optimized for parsing and formatting.  They are stored in
+  // a locale's facet array and accessed via __use_cache<_Facet>.
+  //
+  // The intent twofold: to avoid the costs of creating a locale
+  // object and to avoid calling the virtual functions in a locale's
+  // facet to look up data.
+  class __locale_cache_base
+  {
+    friend class std::locale::_Impl;
+    friend class locale;
+
+  public:
+    virtual
+    ~__locale_cache_base() { }
+
+  };
+
+  // This template doesn't really get used for anything except a
+  // placeholder for specializations
+  template<typename _Facet>
+    class __locale_cache : public __locale_cache_base
+    {
+      // ctor
+      __locale_cache(const locale&) {}
+    };
+
+  template<typename _CharT>
+    class __locale_cache<numpunct<_CharT> > : public __locale_cache_base
+    {
+      // Types:
+      typedef _CharT               	char_type;
+      typedef char_traits<_CharT>       traits_type;
+      typedef basic_string<_CharT>	string_type;
+      
+    public:
+      // Data Members:
+
+      // The sign used to separate decimal values: for standard US
+      // locales, this would usually be: "."  Abstracted from
+      // numpunct::decimal_point().
+      _CharT                    _M_decimal_point;
+
+      // The sign used to separate groups of digits into smaller
+      // strings that the eye can parse with less difficulty: for
+      // standard US locales, this would usually be: "," Abstracted
+      // from numpunct::thousands_sep().
+      _CharT                    _M_thousands_sep;
+      
+      // However the US's "false" and "true" are translated.  From
+      // numpunct::truename() and numpunct::falsename(), respectively.
+      const _CharT*		_M_truename;
+      const _CharT*		_M_falsename;
+
+      // If we are checking groupings. This should be equivalent to
+      // numpunct::groupings().size() != 0
+      bool                      _M_use_grouping;
+
+      // If we are using numpunct's groupings, this is the current
+      // grouping string in effect (from numpunct::grouping()).
+      const char*               _M_grouping;
+
+      // A list of valid numeric literals: for the standard "C"
+      // locale, this is "-+xX0123456789abcdef0123456789ABCDEF".  This
+      // array contains the chars after having been passed through the
+      // current locale's ctype<_CharT>.widen().
+
+      // Copied here from __locale_cache<ctype> to save multiple cache
+      // access in num_put functions.
+      _CharT                    _M_atoms_out[__num_base::_S_end];
+
+      // ctor
+      __locale_cache(const locale& __loc);
+      __locale_cache(const locale& __loc, bool);
+
+      ~__locale_cache()
+      {
+	delete [] _M_truename;
+	delete [] _M_falsename;
+	delete [] _M_grouping;
+      }
+    };
 } // namespace std
 
 #endif
Index: include/bits/locale_facets.tcc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/locale_facets.tcc,v
retrieving revision 1.82.4.10
diff -u -r1.82.4.10 locale_facets.tcc
--- include/bits/locale_facets.tcc	2 May 2003 01:08:04 -0000	1.82.4.10
+++ include/bits/locale_facets.tcc	30 Jun 2003 04:00:54 -0000
@@ -86,6 +86,23 @@
       return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
     }
 
+  // Routine to access a cache for the locale.  If the cache didn't
+  // exist before, it gets constructed on the fly.
+  template<typename _Facet>
+    inline const __locale_cache<_Facet>&
+    __use_cache(const locale& __loc)
+    {
+      size_t __i = _Facet::id._M_id();
+      if (__builtin_expect(__i >= __loc._M_impl->_M_facets_size,false))
+	__throw_bad_cast();
+      __locale_cache_base* __cache = __loc._M_impl->_M_get_cache(__i);
+      if (__builtin_expect(!__cache, false))
+	{
+	  __cache = new __locale_cache<_Facet>(__loc);
+	  __loc._M_impl->_M_install_cache(__cache, __i);
+	}
+      return static_cast<const __locale_cache<_Facet>&>(*__cache);
+    }
 
   // Stage 1: Determine a conversion specifier.
   template<typename _CharT, typename _InIter>
@@ -768,19 +785,16 @@
       _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, 
 		     _ValueT __v) const
       {
+	typedef numpunct<_CharT>  __facet_type;
+	typedef __locale_cache<numpunct<_CharT> > __cache_type;
+ 	const locale& __loc = __io._M_getloc();
+	const __cache_type& __lc = __use_cache<__facet_type>(__loc);
+	const _CharT* __lit = __lc._M_atoms_out;
+
 	// Long enough to hold hex, dec, and octal representations.
 	int __ilen = 4 * sizeof(_ValueT);
 	_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
 							     * __ilen));
-	// Buildup list of digits given the current ctype.
-	_CharT __lit[_S_end];
-	const locale __loc = __io.getloc();
-	if (__builtin_expect(has_facet<ctype<_CharT> >(__loc), true))
-	  {
-	    const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
-	    __ct.widen(_S_atoms_out, _S_atoms_out + _S_end, __lit);
-	  }
-
 	// [22.2.2.2.2] Stage 1, numeric conversion to character.
 	// Result is returned right-justified in the buffer.
 	int __len;
@@ -788,16 +802,14 @@
 	__cs = __cs + __ilen - __len;
 	
 	// Add grouping, if necessary. 
-	const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
-	const string __grouping = __np.grouping();
 	_CharT* __cs2;
-	if (__grouping.size())
+	if (__lc._M_use_grouping)
 	  {
 	    // Grouping can add (almost) as many separators as the
 	    // number of digits, but no more.
 	    __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
 							  * __len * 2));
-	    _M_group_int(__grouping, __np.thousands_sep(), __io, 
+	    _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, 
 			 __cs2, __cs, __len);
 	    __cs = __cs2;
 	  }
@@ -879,6 +891,11 @@
 	else if (__prec < static_cast<streamsize>(0))
 	  __prec = static_cast<streamsize>(6);
 
+	typedef numpunct<_CharT>  __facet_type;
+	typedef __locale_cache<numpunct<_CharT> > __cache_type;
+	const locale __loc = __io._M_getloc();
+	const __cache_type& __lc = __use_cache<__facet_type>(__loc);
+
 	// [22.2.2.2.2] Stage 1, numeric conversion to character.
 	int __len;
 	// Long enough for the max format spec.
@@ -922,7 +939,6 @@
 
       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
       // numpunct.decimal_point() values for '.' and adding grouping.
-      const locale __loc = __io.getloc();
       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
 
       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
@@ -930,23 +946,21 @@
       __ctype.widen(__cs, __cs + __len, __ws);
       
       // Replace decimal point.
-      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
       const _CharT __cdec = __ctype.widen('.');
-      const _CharT __dec = __np.decimal_point();
+      const _CharT __dec = __lc._M_decimal_point;
       const _CharT* __p;
       if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
 	__ws[__p - __ws] = __dec;
 
       // Add grouping, if necessary. 
       _CharT* __ws2;
-      const string __grouping = __np.grouping();
-      if (__grouping.size())
+      if (__lc._M_use_grouping)
 	{
 	    // Grouping can add (almost) as many separators as the
 	    // number of digits, but no more.
-	    __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
+	    __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
 							  * __len * 2));
-	    _M_group_float(__grouping, __np.thousands_sep(), __p, 
+	    _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p,
 			   __ws2, __ws, __len);
 	    __ws = __ws2;
 	}
@@ -980,14 +994,17 @@
         }
       else
         {
-          locale __loc = __io.getloc();
-	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
+	  typedef numpunct<_CharT>  __facet_type;
+	  typedef __locale_cache<numpunct<_CharT> > __cache_type;
+	  const locale __loc = __io._M_getloc();
+	  const __cache_type& __lc = __use_cache<__facet_type>(__loc);
+
 	  typedef basic_string<_CharT> 	__string_type;
 	  __string_type __name;
           if (__v)
-	    __name = __np.truename();
+	    __name = __lc._M_truename;
           else
-	    __name = __np.falsename();
+	    __name = __lc._M_falsename;
 
 	  const _CharT* __cs = __name.c_str();
 	  int __len = __name.size();
@@ -2442,6 +2459,69 @@
       return __write(__s, __ws, __len);
     }
 #endif
+
+  template<typename _CharT>
+    __locale_cache<numpunct<_CharT> >::__locale_cache(const locale& __loc)
+      : _M_truename(0), _M_falsename(0), _M_use_grouping(false),
+	_M_grouping(0)
+    {
+      if (has_facet<numpunct<_CharT> >(__loc))
+	{
+	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
+	  _M_decimal_point = __np.decimal_point();
+	  _M_thousands_sep = __np.thousands_sep();
+
+	  string_type __false = __np.falsename();
+	  _CharT* __falsename = new _CharT[__false.length() + 1];
+	  __false.copy(__falsename, __false.length());
+	  __falsename[__false.length()] = _CharT();
+	  _M_falsename = __falsename;
+
+	  string_type __true = __np.truename();
+	  _CharT* __truename = new _CharT[__true.length() + 1];
+	  __true.copy(__truename, __true.length());
+	  __truename[__true.length()] = _CharT();
+	  _M_truename = __truename;
+
+	  string __grouping = __np.grouping();
+	  char* __group = new char[__grouping.length() + 1];
+	  __grouping.copy(__group, __grouping.length());
+	  __group[__grouping.length()] = 0;
+	  _M_grouping = __group;
+
+	  _M_use_grouping = __grouping.length() != 0 
+	    && __grouping.data()[0] != 0;
+	}
+
+      if (has_facet<ctype<_CharT> >(__loc))
+	{
+	  const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
+	  __ct.widen(__num_base::_S_atoms_out,
+		     __num_base::_S_atoms_out + __num_base::_S_end, 
+		     _M_atoms_out);
+	}
+    }
+
+  // Static locale cache initialization.  Only instantiated with char
+  // and wchar_t, so no need to check has_facet.
+  template<typename _CharT>
+    __locale_cache<numpunct<_CharT> >::
+    __locale_cache(const locale& __loc, bool)
+    {
+      // Grab pointers to numpunct static strings
+      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
+      _M_thousands_sep = __np._M_thousands_sep;
+      _M_decimal_point = __np._M_decimal_point;
+      _M_falsename = __np._M_falsename;
+      _M_truename = __np._M_truename;
+      _M_grouping = __np._M_grouping;
+      _M_use_grouping = false;
+
+      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
+      __ct.widen(__num_base::_S_atoms_out,
+		 __num_base::_S_atoms_out + __num_base::_S_end, 
+		 _M_atoms_out);
+    }
 
   // Inhibit implicit instantiations for required instantiations,
   // which are defined via explicit instantiations elsewhere.  
Index: src/globals.cc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/src/globals.cc,v
retrieving revision 1.12.4.3
diff -u -r1.12.4.3 globals.cc
--- src/globals.cc	2 May 2003 01:08:04 -0000	1.12.4.3
+++ src/globals.cc	30 Jun 2003 04:00:54 -0000
@@ -81,7 +81,7 @@
 
   typedef char fake_facet_vec[sizeof(locale::facet*)]
   __attribute__ ((aligned(__alignof__(locale::facet*))));
-  fake_facet_vec facet_vec[_GLIBCPP_NUM_FACETS];
+  fake_facet_vec facet_vec[2 * _GLIBCPP_NUM_FACETS];
   _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx9facet_vecE, _ZSt9facet_vec, GLIBCPP_3.2)
 
   typedef char fake_ctype_c[sizeof(std::ctype<char>)]
@@ -222,6 +222,17 @@
   __attribute__ ((aligned(__alignof__(messages<wchar_t>))));
   fake_messages_w messages_w;
   _GLIBCPP_ASM_SYMVER(_ZN9__gnu_cxx10messages_wE, _ZSt10messages_w, GLIBCPP_3.2)
+#endif
+
+  // Storage for static C locale caches
+  typedef char fake_locale_cache_c[sizeof(std::__locale_cache<numpunct<char> >)]
+  __attribute__ ((aligned(__alignof__(std::__locale_cache<numpunct<char> >))));
+  fake_locale_cache_c locale_cache_c;
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+  typedef char fake_locale_cache_w[sizeof(std::__locale_cache<numpunct<wchar_t> >)]
+  __attribute__ ((aligned(__alignof__(std::__locale_cache<numpunct<wchar_t> >))));
+  fake_locale_cache_w locale_cache_w;
 #endif
 
   typedef char fake_filebuf[sizeof(stdio_filebuf<char>)]
Index: src/locale-inst.cc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/src/locale-inst.cc,v
retrieving revision 1.35.4.4
diff -u -r1.35.4.4 locale-inst.cc
--- src/locale-inst.cc	2 May 2003 01:08:04 -0000	1.35.4.4
+++ src/locale-inst.cc	30 Jun 2003 04:00:54 -0000
@@ -45,6 +45,7 @@
   template class moneypunct_byname<char, true>;
   template class money_get<char, istreambuf_iterator<char> >;
   template class money_put<char, ostreambuf_iterator<char> >;
+  template class __locale_cache<numpunct<char> >;
 
 #ifdef _GLIBCPP_USE_WCHAR_T
   template class moneypunct<wchar_t, false>;
@@ -53,6 +54,7 @@
   template class moneypunct_byname<wchar_t, true>;
   template class money_get<wchar_t, istreambuf_iterator<wchar_t> >;
   template class money_put<wchar_t, ostreambuf_iterator<wchar_t> >;
+  template class __locale_cache<numpunct<wchar_t> >;
 #endif
 
   // numpunct, numpunct_byname, num_get, and num_put
@@ -461,6 +463,17 @@
   template 
     bool
     has_facet<messages<wchar_t> >(const locale&);
+#endif
+
+  // __use_cache
+  template
+    const __locale_cache<numpunct<char> >&
+    __use_cache<numpunct<char> >(const locale& __loc);
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+   template
+    const __locale_cache<numpunct<wchar_t> >&
+    __use_cache<numpunct<wchar_t> >(const locale& __loc);
 #endif
 
   // locale
Index: src/localename.cc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/src/localename.cc,v
retrieving revision 1.33.2.3
diff -u -r1.33.2.3 localename.cc
--- src/localename.cc	25 Apr 2003 18:18:05 -0000	1.33.2.3
+++ src/localename.cc	30 Jun 2003 04:00:55 -0000
@@ -35,7 +35,7 @@
   using namespace std;
 
   // Defined in globals.cc.
-  extern locale::facet* facet_vec[_GLIBCPP_NUM_FACETS];
+  extern locale::facet* facet_vec[2 * _GLIBCPP_NUM_FACETS];
   extern char* facet_name[6 + _GLIBCPP_NUM_CATEGORIES];
 
   extern std::ctype<char>			ctype_c;
@@ -68,6 +68,11 @@
   extern time_put<wchar_t> 			time_put_w;
   extern std::messages<wchar_t> 		messages_w;
 #endif
+
+  extern std::__locale_cache<numpunct<char> >	locale_cache_numpunct_c;
+#ifdef  _GLIBCPP_USE_WCHAR_T
+  extern std::__locale_cache<numpunct<wchar_t> >	locale_cache_numpunct_w;
+#endif
 } // namespace __gnu_cxx
 
 namespace std
@@ -77,9 +82,13 @@
   locale::_Impl::
   ~_Impl() throw()
   {
+    // Clean up facets, then caches.  No cache refcounts for now.
     for (size_t __i = 0; __i < _M_facets_size; ++__i)
       if (_M_facets[__i])
 	_M_facets[__i]->_M_remove_reference();
+    for (size_t __i = _M_facets_size; __i < 2*_M_facets_size; ++__i)
+      if (_M_facets[__i])
+	delete (__locale_cache_base*)_M_facets[__i];
     delete [] _M_facets;
 
     for (size_t __i = 0; 
@@ -94,8 +103,9 @@
   {
     try
       { 
-	_M_facets = new facet*[_M_facets_size]; 
-	for (size_t __i = 0; __i < _M_facets_size; ++__i)
+	// Space for facets and matching caches
+	_M_facets = new facet*[2*_M_facets_size]; 
+	for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
 	  _M_facets[__i] = 0;
       }
     catch(...) 
@@ -129,9 +139,10 @@
     locale::facet::_S_create_c_locale(__cloc, __s);
 
     try
-      { 
-	_M_facets = new facet*[_M_facets_size]; 
-	for (size_t __i = 0; __i < _M_facets_size; ++__i)
+      {
+	// Space for facets and matching caches
+	_M_facets = new facet*[2*_M_facets_size]; 
+	for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
 	  _M_facets[__i] = 0;
       }
     catch(...) 
@@ -214,8 +225,9 @@
     locale::facet::_S_create_c_locale(locale::facet::_S_c_locale, 
 				      locale::facet::_S_c_name);
 
-    _M_facets = new(&facet_vec) facet*[_M_facets_size];
-    for (size_t __i = 0; __i < _M_facets_size; ++__i)
+    // Space for facets and matching caches
+    _M_facets = new(&facet_vec) facet*[2*_M_facets_size];
+    for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
       _M_facets[__i] = 0;
 
     // Name all the categories.
@@ -263,6 +275,25 @@
     _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
     _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
 #endif 
+
+    // Initialize the static locale caches for C locale.
+
+    locale ltmp(this);		// Doesn't bump refcount
+    _M_add_reference();		// Bump so destructor doesn't trash us
+
+    // These need to be built in static allocated memory.  There must
+    // be a better way to do this!
+    __locale_cache<numpunct<char> >* __lc =
+      new (&locale_cache_c) __locale_cache<numpunct<char> >(ltmp, true);
+    _M_facets[numpunct<char>::id._M_id() + _M_facets_size] =
+      reinterpret_cast<locale::facet*>(__lc);
+      
+#ifdef  _GLIBCPP_USE_WCHAR_T
+    __locale_cache<numpunct<wchar_t> >* __wlc =
+      new (&locale_cache_w) __locale_cache<numpunct<wchar_t> >(ltmp, true);
+    _M_facets[numpunct<wchar_t>::id._M_id() + _M_facets_size] =
+      reinterpret_cast<locale::facet*>(__wlc);
+#endif    
   }
   
   void



More information about the Libstdc++ mailing list