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]

[v3] move locale cache to 3.3


I've gotten the locale cache stuff working in 3.3 and it passes make
check-abi.  I'm storing the cache in pword(0) to avoid changing the ios_base
size.

The patch assumes http://gcc.gnu.org/ml/libstdc++/2003-02/msg00433.html is
applied without modification to 3.3.

There were a couple of fixups to it, though.  I had to export _S_atoms_in and
_S_atoms_out and reinsert _S_atoms to get check-abi to work.

Also, there were two latent bugs in ios_base::_M_grow_words.  First, we don't
actually want to delete the _Words array if a new allocation fails.
Otherwise, you could be calling callbacks that look for data that isn't there
any longer.  The spec only says that badbit should be set, and if we delete
the array, later callbacks will still be expecting that data to be there.
Second, if the number is too large, we need to throw a failure exception if
the exception mask has badbit set.

What do you think?  The pword stuff is not quite as pretty, but it's still
fast.


2003-03-02  Jerry Quinn  <jlquinn at optonline dot net>

        * config/linker-map.gnu (__num_base::_S_atoms_in,
        __num_base::_S_atoms_out): Export symbols in 3.2.3.
	* include/bits/basic_ios.h:  Update copyright.
	(_M_cache_locale): New.
	(_M_cache_facets): Deprecate.
	* include/bits/basic_ios.tcc (basic_ios::copyfmt):  Set up locale
        caching.
	(basic_ios::imbue,basic_ios::init): Use _M_cache_locale.
	(basic_ios::_M_cache_locale): New.
	(basic_ios::_M_cache_facets): Deprecate.
	* include/bits/ios_base.h (__locale_cache_base): Declare.
	(ios_base::_M_cache): Define.
	* include/bits/locale_facets.h (__num_base): Add _S_end to enum.
	(_S_atoms): Restore.
	(__locale_cache_base,__locale_cache<_CharT>):  New classes.
	* include/bits/locale_facets.tcc (num_put::_M_convert_int): Use locale
	cache literal string, grouping flag, thousands separator.
	(num_out::_M_convert_float): Use locale cache grouping flag, decimal
        point, thousands separator.
	(__locale_cache<_CharT>::_M_init,__locale_cache<_CharT>::_S_callback):
        New.
	* src/ios.cc (ios_base::_M_grow_words): Don't delete _M_word on new
        failure.  Throw exception if badbit and exception mask when ix >=
        numeric_limits<int>::max().
	* src/locale-inst.cc (__locale_cache<_CharT>::_S_callback,
        __locale_cache<char>, __locale_cache<wchar_t>): New.
	* src/locale.cc (_S_atoms): Restore deprecated definition.

diff -r -u libstdc++.33.precache/config/linker-map.gnu libstdc++-v3/config/linker-map.gnu
--- libstdc++.33.precache/config/linker-map.gnu	Fri Feb 28 22:48:25 2003
+++ libstdc++-v3/config/linker-map.gnu	Sat Mar  1 20:09:41 2003
@@ -272,6 +272,9 @@
       __gnu_cxx::__gthread_atomic_add_mutex_once
     };
 
+  _ZNSt10__num_base11_S_atoms_inE;
+  _ZNSt10__num_base12_S_atoms_outE;
+
   _ZNKSt7num_putI[wc]St19ostreambuf_iteratorI[wc]St11char_traitsI[wc]EEE6_M_pad*;
 
   _ZNKSt7num_putI[wc]St19ostreambuf_iteratorI[wc]St11char_traitsI[wc]EEE14_M_group_float*;
diff -r -u libstdc++.33.precache/include/bits/basic_ios.h libstdc++-v3/include/bits/basic_ios.h
--- libstdc++.33.precache/include/bits/basic_ios.h	Fri Feb 28 22:48:33 2003
+++ libstdc++-v3/include/bits/basic_ios.h	Sat Mar  1 14:25:54 2003
@@ -1,6 +1,6 @@
 // Iostreams base classes -*- C++ -*-
 
-// Copyright (C) 1997, 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+// Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -431,7 +431,13 @@
       }
 
       void
+      _M_cache_locale(const locale& __loc);
+
+#if 1
+      // XXX GLIBCXX_ABI Deprecated, compatibility only.
+      void
       _M_cache_facets(const locale& __loc);
+#endif
     };
 } // namespace std
 
diff -r -u libstdc++.33.precache/include/bits/basic_ios.tcc libstdc++-v3/include/bits/basic_ios.tcc
--- libstdc++.33.precache/include/bits/basic_ios.tcc	Fri Feb 28 22:48:33 2003
+++ libstdc++-v3/include/bits/basic_ios.tcc	Sat Mar  1 23:40:13 2003
@@ -95,10 +95,17 @@
       this->precision(__rhs.precision());
       this->tie(__rhs.tie());
       this->fill(__rhs.fill());
+      _M_ios_locale = __rhs.getloc();
+
+      // This removes the link to __rhs locale cache
+      _M_call_callbacks(copyfmt_event);
+
+      _M_cache_locale(_M_ios_locale);
+
+
       // The next is required to be the last assignment.
       this->exceptions(__rhs.exceptions());
       
-      _M_call_callbacks(copyfmt_event);
       return *this;
     }
 
@@ -129,7 +136,7 @@
     {
       locale __old(this->getloc());
       ios_base::imbue(__loc);
-      _M_cache_facets(__loc);
+      _M_cache_locale(__loc);
       if (this->rdbuf() != 0)
 	this->rdbuf()->pubimbue(__loc);
       return __old;
@@ -141,7 +148,7 @@
     {
       // NB: This may be called more than once on the same object.
       ios_base::_M_init();
-      _M_cache_facets(_M_ios_locale);
+      _M_cache_locale(_M_ios_locale);
       _M_tie = 0;
 
       // NB: The 27.4.4.1 Postconditions Table specifies requirements
@@ -166,22 +173,42 @@
 
   template<typename _CharT, typename _Traits>
     void
-    basic_ios<_CharT, _Traits>::_M_cache_facets(const locale& __loc)
+    basic_ios<_CharT, _Traits>::_M_cache_locale(const locale& __loc)
     {
-      if (has_facet<__ctype_type>(__loc))
+      if (__builtin_expect(has_facet<__ctype_type>(__loc), true))
 	_M_fctype = &use_facet<__ctype_type>(__loc);
       else
 	_M_fctype = 0;
-      // Should be filled in by ostream and istream, respectively.
-      if (has_facet<__numput_type>(__loc))
+      if (__builtin_expect(has_facet<__numput_type>(__loc), true))
 	_M_fnumput = &use_facet<__numput_type>(__loc); 
       else
 	_M_fnumput = 0;
-      if (has_facet<__numget_type>(__loc))
-	_M_fnumget = &use_facet<__numget_type>(__loc); 
+      if (__builtin_expect(has_facet<__numget_type>(__loc), true))
+	_M_fnumget = &use_facet<__numget_type>(__loc);
       else
 	_M_fnumget = 0;
+      typedef __locale_cache<_CharT> __cache_t;
+      if (!pword(0)) {
+	pword(0) = auto_ptr<__cache_t>(new __cache_t()).release();
+	register_callback(__cache_t::_S_callback, 0);
+      }
+      static_cast<__cache_t&>(_M_cache())._M_init(__loc);
+    }
+
+#if 1
+      // XXX GLIBCXX_ABI Deprecated, compatibility only.
+  template<typename _CharT, typename _Traits>
+    void
+    basic_ios<_CharT, _Traits>::_M_cache_facets(const locale& __loc)
+    {
+      if (__builtin_expect(has_facet<__ctype_type>(__loc), true))
+	_M_fctype = &use_facet<__ctype_type>(__loc);
+      if (__builtin_expect(has_facet<__numput_type>(__loc), true))
+	_M_fnumput = &use_facet<__numput_type>(__loc); 
+      if (__builtin_expect(has_facet<__numget_type>(__loc), true))
+	_M_fnumget = &use_facet<__numget_type>(__loc);
     }
+#endif
 
   // Inhibit implicit instantiations for required instantiations,
   // which are defined via explicit instantiations elsewhere.  
diff -r -u libstdc++.33.precache/include/bits/ios_base.h libstdc++-v3/include/bits/ios_base.h
--- libstdc++.33.precache/include/bits/ios_base.h	Fri Feb 28 22:48:33 2003
+++ libstdc++-v3/include/bits/ios_base.h	Sat Mar  1 12:32:49 2003
@@ -146,6 +146,8 @@
 
   enum _Ios_Seekdir { _M_ios_seekdir_end = 1L << 16 };
 
+  class __locale_cache_base;
+
   // 27.4.2  Class ios_base
   /**
    *  @brief  The very top of the I/O class hierarchy.
@@ -635,6 +637,11 @@
 			? _M_word[__ix] : _M_grow_words(__ix);
       return __word._M_pword;
     }
+
+    // Access to the cache.  Not safe to call until basic_ios::_M_init() has
+    // happened.
+    __locale_cache_base&
+    _M_cache() { return *static_cast<__locale_cache_base*>(pword(0)); }
 
     // Destructor
     /**
diff -r -u libstdc++.33.precache/include/bits/locale_facets.h libstdc++-v3/include/bits/locale_facets.h
--- libstdc++.33.precache/include/bits/locale_facets.h	Fri Feb 28 22:48:33 2003
+++ libstdc++-v3/include/bits/locale_facets.h	Sat Mar  1 14:58:44 2003
@@ -543,8 +543,9 @@
         _S_digits_end = _S_digits + 16,
         _S_udigits = _S_digits_end,  
         _S_udigits_end = _S_udigits + 16,
-        _S_e = _S_digits + 14, // For scientific notation, 'e'
-        _S_E = _S_udigits + 14 // For scientific notation, 'E'
+        _S_e = _S_digits + 14,  // For scientific notation, 'e'
+        _S_E = _S_udigits + 14, // For scientific notation, 'E'
+	_S_end = _S_udigits_end
       };
     
     // A list of valid numeric literals for output. 
@@ -559,6 +560,12 @@
     // "0123456789eEabcdfABCDF"
     static const char* _S_atoms_in;
 
+#if 1
+    // XXX GLIBCXX_ABI Deprecated, compatibility only.
+    // Now use _S_atoms_in
+    static const char _S_atoms[];
+#endif    
+
     enum 
     {  
       _M_zero,
@@ -1952,6 +1959,80 @@
     inline _CharT 
     tolower(_CharT __c, const locale& __loc)
     { return use_facet<ctype<_CharT> >(__loc).tolower(__c); }
+
+  // __locale_cache holds the information extracted from the
+  // numpunct<> and moneypunct<> facets in a form optimized for
+  // parsing and formatting.  To avoid breaking the 3.2 library
+  // API, it is stored in ios_base::_M_local_word[0]. as a member of basic_ios and accessed via a void* pointer in
+  // the ios_base object passed to the _get and _put facets.
+
+  // Its intent is to avoid the cost of creating a locale object and
+  // calling the virtual functions in locale facets.
+  class __locale_cache_base
+  {
+  public:
+    virtual
+    ~__locale_cache_base() {}
+  };
+
+  template<typename _CharT>
+    class __locale_cache : public __locale_cache_base
+    {
+      // Types:
+      typedef _CharT               	char_type;
+      typedef char_traits<_CharT>       traits_type;
+      typedef basic_string<_CharT>	string_type;
+
+
+    public: 
+      // Data Members:
+
+      // 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().
+      _CharT                    _M_literals[__num_base::_S_end];
+
+     
+      // 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.
+      string_type 		_M_truename;
+      string_type 		_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()).
+      string                    _M_grouping;
+
+      __locale_cache() : _M_use_grouping(false)
+      { };
+
+      __locale_cache&
+      operator=(const __locale_cache& __lc);
+
+
+      // Make sure the cache is built before the first use.
+      void
+      _M_init(const locale&);
+
+      // ios_base::pword callbacks come here
+      static void
+      _S_callback(ios_base::event __ev, ios_base& __io, int);
+    };
 } // namespace std
 
 #endif
diff -r -u libstdc++.33.precache/include/bits/locale_facets.tcc libstdc++-v3/include/bits/locale_facets.tcc
--- libstdc++.33.precache/include/bits/locale_facets.tcc	Fri Feb 28 22:48:33 2003
+++ libstdc++-v3/include/bits/locale_facets.tcc	Sun Mar  2 01:01:00 2003
@@ -768,14 +768,9 @@
       _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, 
 		     _ValueT __v) const
       {
-	// Buildup list of digits given the current ctype.
-	_CharT __lit[_S_udigits_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_udigits_end, __lit);
-	  }
+        typedef __locale_cache<_CharT> __cache_type;
+        __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache());
+        _CharT* __lit = __lc._M_literals;
 
 	// Long enough to hold hex, dec, and octal representations.
 	int __ilen = 4 * sizeof(_ValueT);
@@ -790,15 +785,13 @@
 	
 	// Add grouping, if necessary. 
 	_CharT* __cs2;
-	const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
-	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.
 	    __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 +873,9 @@
 	else if (__prec < static_cast<streamsize>(0))
 	  __prec = static_cast<streamsize>(6);
 
+        typedef __locale_cache<_CharT> __cache_type;
+        __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache());
+
 	// [22.2.2.2.2] Stage 1, numeric conversion to character.
 	int __len;
 	// Long enough for the max format spec.
@@ -925,7 +921,6 @@
       // numpunct.decimal_point() values for '.' and adding grouping.
       const locale __loc = __io.getloc();
       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
 
       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
 							   * __len));
@@ -933,21 +928,20 @@
       
       // Replace decimal point.
       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) 
 							  * __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;
 	}
@@ -2214,6 +2208,55 @@
 	*__s++ = *__first++;
       while (__first != __last);
       return __s;
+    }
+
+  template<typename _CharT>
+    void
+    __locale_cache<_CharT>::_M_init(const locale& __loc)
+    {
+      if (__builtin_expect(has_facet<numpunct<_CharT> >(__loc), true))
+        {
+          const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
+          _M_falsename = __np.falsename();
+          _M_truename = __np.truename();
+          _M_thousands_sep = __np.thousands_sep();
+          _M_decimal_point = __np.decimal_point();
+          _M_grouping = __np.grouping();
+          _M_use_grouping = _M_grouping.size() != 0 
+                            && _M_grouping.data()[0] != 0;
+        }
+      if (__builtin_expect(has_facet<ctype<_CharT> >(__loc), true))
+        {
+          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_literals);
+        }
+    }
+
+  template<typename _CharT>
+    void
+    __locale_cache<_CharT>::_S_callback(ios_base::event __ev, ios_base& __io, int)
+    {
+      switch (__ev)
+	{
+	case ios_base::erase_event:
+	  if (__io.pword(0))
+	    delete &__io._M_cache();
+	  break;
+
+	case ios_base::imbue_event:
+	  break;
+
+	case ios_base::copyfmt_event:
+	  // This routine is called with the new ios_base, but pword(0) still
+	  // points to the cache from the old ios_base.  This replaces it with
+	  // a new cache.  Done here, so we don't get an extra callback from
+	  // basic_ios::_M_cache_locale.
+	  typedef __locale_cache<_CharT> __cache_t;
+	  __io.pword(0) = auto_ptr<__cache_t>(new __cache_t()).release();
+	  break;
+	}
     }
 
 #if 1
diff -r -u libstdc++.33.precache/src/ios.cc libstdc++-v3/src/ios.cc
--- libstdc++.33.precache/src/ios.cc	Fri Feb 28 22:48:36 2003
+++ libstdc++-v3/src/ios.cc	Sun Mar  2 01:11:53 2003
@@ -253,8 +253,6 @@
 	      { words = new _Words[newsize]; }
 	    catch (...)
 	      {
-		delete [] _M_word;
-		_M_word = 0;
 		_M_streambuf_state |= badbit;
 		if (_M_streambuf_state & _M_exception)
 		  __throw_ios_failure("ios_base::_M_grow_words failure");
@@ -271,6 +269,8 @@
 	else
 	  {
 	    _M_streambuf_state |= badbit;
+	    if (_M_streambuf_state & _M_exception)
+	      __throw_ios_failure("ios_base::_M_grow_words failure");
 	    return _M_word_zero;
 	  }
       }
diff -r -u libstdc++.33.precache/src/locale-inst.cc libstdc++-v3/src/locale-inst.cc
--- libstdc++.33.precache/src/locale-inst.cc	Fri Feb 28 22:48:36 2003
+++ libstdc++-v3/src/locale-inst.cc	Sat Mar  1 13:38:43 2003
@@ -545,4 +545,13 @@
 		  ios_base::fmtflags, bool);
 #endif
 #endif
+
+  template<typename _CharT>
+    void
+    __locale_cache<_CharT>::_S_callback(ios_base::event __ev, ios_base& __io, int);
+
+  template class __locale_cache<char>;
+#ifdef _GLIBCPP_USE_WCHAR_T
+  template class __locale_cache<wchar_t>;
+#endif
 } // namespace std
diff -r -u libstdc++.33.precache/src/locale.cc libstdc++-v3/src/locale.cc
--- libstdc++.33.precache/src/locale.cc	Fri Feb 28 22:48:36 2003
+++ libstdc++-v3/src/locale.cc	Sat Mar  1 14:58:32 2003
@@ -503,6 +503,10 @@
 
   const char* __num_base::_S_atoms_in = "0123456789eEabcdfABCDF";
   const char* __num_base::_S_atoms_out ="-+xX0123456789abcdef0123456789ABCDEF";
+#if 1
+    // XXX GLIBCXX_ABI Deprecated, compatibility only.
+  const char __num_base::_S_atoms[] = "0123456789eEabcdfABCDF";
+#endif
 
   // _GLIBCPP_RESOLVE_LIB_DEFECTS
   // According to the resolution of DR 231, about 22.2.2.2.2, p11,

	

	


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