This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [v3] locale cache PR 7076,8761


B. Kosnik writes:
 > 
 > >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.
 > 
 > Please don't check this in until this has been conclusively resolved.
 > I've not had time to look at this yet.

This is the version with a separate cache array as suggested by
Nathan.  It passes make check with no regressions.  It also violates
abi-check.  In this case, std::c_locale_impl has grown with an extra
pointer at the end of the class (which Nathan believes is safe).
abi-check also believes that std::locale::_Impl::_S_static_caches is
incompatible.

<lightbulb> The previous version doesn't pass abi-check because
facet_vec is too large.  If I left it alone, but created a second
array facet_vec2 and used that instead, then the old array symbol will
still be there and the same size, but we won't use it anymore.  That
should satisfy abi-check.
</lightbulb>

What do you think?

Jerry



2003-07-04  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_caches,_S_static_caches):  New.
	(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
	(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
	(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::_Impl::_M_install_facet):  Expand cache storage.


Index: include/bits/ios_base.h
===================================================================
RCS file: /cvs/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	5 Jul 2003 04:19:03 -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: /cvs/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	5 Jul 2003 04:19:03 -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;
@@ -212,6 +223,13 @@
     static const locale::id* const 	_S_id_messages[];
     static const locale::id* const* const _S_facet_categories[];
 
+    // Storage for locale caches.
+    // If _M_caches != _S_static_caches, they're dynamic.
+    __locale_cache_base**		_M_caches;
+
+    // For char and wchar_t.  Set to 0 by the linker
+    static __locale_cache_base*		_S_static_caches[];
+
     inline void 
     _M_add_reference() throw()
     { __atomic_add(&_M_references, 1); }
@@ -266,6 +284,20 @@
       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 _M_caches[__index]; }
+
+    // Save the supplied cache at __id.  Assumes _M_get_cache has been
+    // called.
+    void
+    _M_install_cache(__locale_cache_base* __cache, int __id)
+    { _M_caches[__id] = __cache; }
+      
   };
 
   template<typename _Facet>
Index: include/bits/locale_facets.h
===================================================================
RCS file: /cvs/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	5 Jul 2003 04:19:03 -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: /cvs/gcc/gcc/libstdc++-v3/include/bits/locale_facets.tcc,v
retrieving revision 1.82.4.11
diff -u -r1.82.4.11 locale_facets.tcc
--- include/bits/locale_facets.tcc	5 Jul 2003 03:36:54 -0000	1.82.4.11
+++ include/bits/locale_facets.tcc	5 Jul 2003 04:19:04 -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>
@@ -769,19 +786,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;
@@ -789,16 +803,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;
 	  }
@@ -880,6 +892,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.
@@ -923,7 +940,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) 
@@ -931,23 +947,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;
 	}
@@ -981,14 +995,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();
@@ -2443,6 +2460,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: /cvs/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	5 Jul 2003 04:19:04 -0000
@@ -224,6 +224,17 @@
   _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>)]
   __attribute__ ((aligned(__alignof__(stdio_filebuf<char>))));
   fake_filebuf buf_cout;
Index: src/locale-inst.cc
===================================================================
RCS file: /cvs/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	5 Jul 2003 04:19:05 -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: /cvs/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	5 Jul 2003 04:19:05 -0000
@@ -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_c;
+#ifdef  _GLIBCPP_USE_WCHAR_T
+  extern std::__locale_cache<numpunct<wchar_t> >	locale_cache_w;
+#endif
 } // namespace __gnu_cxx
 
 namespace std
@@ -84,7 +89,15 @@
 
     for (size_t __i = 0; 
 	 __i < _S_categories_size + _S_extra_categories_size; ++__i)
-      delete [] _M_names[__i];  
+      delete [] _M_names[__i];
+
+    // Clean up caches.  No refcount for now.
+    if (_M_caches != _S_static_caches)
+      {
+	for (size_t __i = 0; __i < _M_facets_size; ++__i)
+	  delete _M_caches[__i];
+	delete [] _M_caches;
+      }
   }
 
   // Clone existing _Impl object.
@@ -116,6 +129,18 @@
 	strcpy(__new, __imp._M_names[__i]);
 	_M_names[__i] = __new;
       }
+    // Allocate cache storage
+    try
+      { 
+	_M_caches = new __locale_cache_base*[_M_facets_size];
+	for (size_t __i = 0; __i < _M_facets_size; ++__i)
+	  _M_caches[__i] = 0;
+      }
+    catch(...) 
+      {
+	delete [] _M_facets;
+	__throw_exception_again;
+      }
   }
 
   // Construct named _Impl.
@@ -129,7 +154,7 @@
     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)
 	  _M_facets[__i] = 0;
@@ -168,6 +193,19 @@
 	  }
       }
 
+    // Allocate cache storage
+    try
+      { 
+	_M_caches = new __locale_cache_base*[_M_facets_size];
+	for (size_t __i = 0; __i < _M_facets_size; ++__i)
+	  _M_caches[__i] = 0;
+      }
+    catch(...) 
+      {
+	delete [] _M_facets;
+	__throw_exception_again;
+      }
+
     // Construct all standard facets and add them to _M_facets.  
     _M_init_facet(new std::ctype<char>(__cloc, 0, false));
     _M_init_facet(new codecvt<char, char, mbstate_t>);
@@ -203,10 +241,13 @@
     locale::facet::_S_destroy_c_locale(__cloc);
   }
 
+  __locale_cache_base* locale::_Impl::_S_static_caches[_GLIBCPP_NUM_FACETS];
+
   // Construct "C" _Impl.
   locale::_Impl::
   _Impl(facet**, size_t __refs, bool) 
-  : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
+    : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS),
+      _M_caches(_S_static_caches)
   {
     // Initialize the underlying locale model.
     locale::facet::_S_c_name[0] = 'C';
@@ -263,6 +304,23 @@
     _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_caches[numpunct<char>::id._M_id()] = __lc;
+      
+#ifdef  _GLIBCPP_USE_WCHAR_T
+    __locale_cache<numpunct<wchar_t> >* __wlc =
+      new (&locale_cache_w) __locale_cache<numpunct<wchar_t> >(ltmp, true);
+    _M_caches[numpunct<wchar_t>::id._M_id()] =__wlc;
+#endif    
   }
   
   void
@@ -322,6 +380,7 @@
 	    facet** __old = _M_facets;
 	    facet** __new;
 	    const size_t __new_size = __index + 4;
+	    const size_t __old_size = _M_facets_size;
 	    __new = new facet*[__new_size]; 
 	    for (size_t __i = 0; __i < _M_facets_size; ++__i)
 	      __new[__i] = _M_facets[__i];
@@ -331,6 +390,19 @@
 	    _M_facets_size = __new_size;
 	    _M_facets = __new;
 	    delete [] __old;
+
+	    // Increase size of cache array to match
+	    __locale_cache_base** __old_caches = _M_caches;
+	    __locale_cache_base** __new_caches
+	      = new __locale_cache_base*[__new_size];
+	    for (size_t __i = 0; __i < __old_size; ++__i)
+	      __new_caches[__i] = __old_caches[__i];
+	    for (size_t __i = __old_size; __i < __new_size; ++__i)
+	      __new_caches[__i] = 0;
+
+	    _M_caches = __new_caches;
+	    if (__old_caches != _S_static_caches)
+	      delete [] __old_caches;
 	  }
 
 	__fp->_M_add_reference();


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]