]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ios_base.h (ios_base::_M_getloc): Return reference to the imbued locale.
authorBenjamin Kosnik <bkoz@redhat.com>
Fri, 27 Jun 2003 07:25:38 +0000 (07:25 +0000)
committerBenjamin Kosnik <bkoz@gcc.gnu.org>
Fri, 27 Jun 2003 07:25:38 +0000 (07:25 +0000)
2003-06-26  Benjamin Kosnik  <bkoz@redhat.com>

* include/bits/ios_base.h (ios_base::_M_getloc): Return reference
to the imbued locale.
* include/bits/locale_facets.tcc (num_put::_M_convert_int): Use
_M_getloc.
(num_put::_M_convert_float): Use.

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

* config/linker-map.gnu: Add __numpunct_cache.
* config/locale/gnu/numeric_members.cc
(numpunct::_M_initialize_numpunct): Account for _M_data, fill in
all elements for "C" locale.
(numpunct::~numpunct): Delete _M_data.
* config/locale/generic/numeric_members.cc: Same.
* include/bits/basic_ios.tcc
(basic_ios::init): Remove __locale_cache bits.
(basic_ios::_M_cache_locale): Same.
* include/bits/ios_base.h: Same. Tweaks.
* include/bits/locale_classes.h: Tweaks. Reorder classes.
(__use_cache): Make friends with _Impl, locale.
(_Impl::_M_caches): Add.
(_Impl::_M_install_cache): Add.
* include/bits/locale_facets.h (__numpunct_cache): New.
(numpunct): Encapsulate data members in __numpunct_cache member,
_M_data. Adjust virtuals.
(numpunct::numpunct): New ctor for the same.
(__locale_cache_base): Remove.
(__locale_cache): Remove.
* include/bits/locale_facets.tcc (__use_cache): New function,
specializations.
(num_put::_M_convert_int, _M_convert_float, do_put): Use it.
* src/globals.cc: Add cache_vec, numpunct_cache_c, numpunct_cache_w.
* src/ios.cc (ios_base::ios_base): Remove __locale_cache.
* src/locale-inst.cc: Same. Add __numpunct_cache.
* src/locale.cc: Tweak inlines.
(__use_cache): Define specializations.
* src/localename.cc: Use global bits.
(_Impl::~Impl): Deal with __numpunct_cache destruction.
(_Impl::_Impl): Same. Pre-cache standard numpunct facets.
(_Impl::_M_init_facet): Take into account __numpunct_cache.
* testsuite/27_io/ios_base/cons/assign_neg.cc: Update line numbers.
* testsuite/27_io/ios_base/cons/copy_neg.cc: Same.

Co-Authored-By: Jerry Quinn <jlquinn@optonline.net>
From-SVN: r68558

16 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/config/linker-map.gnu
libstdc++-v3/config/locale/generic/numeric_members.cc
libstdc++-v3/config/locale/gnu/numeric_members.cc
libstdc++-v3/include/bits/basic_ios.tcc
libstdc++-v3/include/bits/ios_base.h
libstdc++-v3/include/bits/locale_classes.h
libstdc++-v3/include/bits/locale_facets.h
libstdc++-v3/include/bits/locale_facets.tcc
libstdc++-v3/src/globals.cc
libstdc++-v3/src/ios.cc
libstdc++-v3/src/locale-inst.cc
libstdc++-v3/src/locale.cc
libstdc++-v3/src/localename.cc
libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc
libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc

index 9e2c2c13761000fa30dd517569311363f52234f2..4572136f010cc851089bc1b6cbb40d8ec8cdfe84 100644 (file)
@@ -1,3 +1,49 @@
+2003-06-26  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * include/bits/ios_base.h (ios_base::_M_getloc): Return reference
+       to the imbued locale.
+       * include/bits/locale_facets.tcc (num_put::_M_convert_int): Use
+       _M_getloc.
+       (num_put::_M_convert_float): Use.
+
+2003-06-26  Benjamin Kosnik  <bkoz@redhat.com>
+           Jerry Quinn  <jlquinn@optonline.net>
+
+       * config/linker-map.gnu: Add __numpunct_cache.
+       * config/locale/gnu/numeric_members.cc
+       (numpunct::_M_initialize_numpunct): Account for _M_data, fill in
+       all elements for "C" locale.
+       (numpunct::~numpunct): Delete _M_data.
+       * config/locale/generic/numeric_members.cc: Same.       
+       * include/bits/basic_ios.tcc
+       (basic_ios::init): Remove __locale_cache bits.
+       (basic_ios::_M_cache_locale): Same.
+       * include/bits/ios_base.h: Same. Tweaks. 
+       * include/bits/locale_classes.h: Tweaks. Reorder classes.
+       (__use_cache): Make friends with _Impl, locale.
+       (_Impl::_M_caches): Add.
+       (_Impl::_M_install_cache): Add.
+       * include/bits/locale_facets.h (__numpunct_cache): New.
+       (numpunct): Encapsulate data members in __numpunct_cache member,
+       _M_data. Adjust virtuals.
+       (numpunct::numpunct): New ctor for the same. 
+       (__locale_cache_base): Remove.
+       (__locale_cache): Remove.       
+       * include/bits/locale_facets.tcc (__use_cache): New function,
+       specializations.
+       (num_put::_M_convert_int, _M_convert_float, do_put): Use it.
+       * src/globals.cc: Add cache_vec, numpunct_cache_c, numpunct_cache_w.
+       * src/ios.cc (ios_base::ios_base): Remove __locale_cache.
+       * src/locale-inst.cc: Same. Add __numpunct_cache.
+       * src/locale.cc: Tweak inlines.
+       (__use_cache): Define specializations.
+       * src/localename.cc: Use global bits.
+       (_Impl::~Impl): Deal with __numpunct_cache destruction.
+       (_Impl::_Impl): Same. Pre-cache standard numpunct facets.
+       (_Impl::_M_init_facet): Take into account __numpunct_cache.
+       * testsuite/27_io/ios_base/cons/assign_neg.cc: Update line numbers.
+       * testsuite/27_io/ios_base/cons/copy_neg.cc: Same.
+
 2003-06-26  Nathan C. Myers  <ncm-nospam@cantrip.org>
             Paolo Carlini  <pcarlini@unitus.it>
 
index 77d69fc72f06b0a9d23b0055eaff09d169cc1858..21bdfd322a87ac9773c69eca1c7024a5c4fc8e2c 100644 (file)
@@ -55,7 +55,8 @@ GLIBCPP_3.4 {
       std::__num_base::_S_format_float*;
       std::__num_base::_S_format_int*;
       std::__num_base::_S_atoms_in;
-      std::__num_base::_S_atoms_out
+      std::__num_base::_S_atoms_out;
+      std::__numpunct_cache*;
     };
 
     # Names not in an 'extern' block are mangled names.
index f942e0415b069ac85e6193e69566c40c6da1cf02..320f0ff4ba1ebbd1f5f813004b8e572741bfa263 100644 (file)
@@ -1,6 +1,6 @@
 // std::numpunct implementation details, generic version -*- C++ -*-
 
-// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -42,16 +42,30 @@ namespace std
     numpunct<char>::_M_initialize_numpunct(__c_locale)
     {
       // "C" locale
-      _M_decimal_point = '.';
-      _M_thousands_sep = ',';
-      _M_grouping = "";
-      _M_truename = "true";
-      _M_falsename = "false";
+      if (!_M_data)
+       _M_data = new __numpunct_cache<char>;
+
+      _M_data->_M_grouping = "";
+      _M_data->_M_use_grouping = false;
+
+      _M_data->_M_decimal_point = '.';
+      _M_data->_M_thousands_sep = ',';
+      
+      for (size_t i = 0; i < __num_base::_S_oend; ++i)
+       _M_data->_M_atoms_out[i] = __num_base::_S_atoms_out[i];
+      _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t();
+      
+      for (size_t i = 0; i < __num_base::_S_iend; ++i)
+       _M_data->_M_atoms_in[i] = __num_base::_S_atoms_in[i];
+      _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t();
+
+      _M_data->_M_truename = "true";
+      _M_data->_M_falsename = "false";      
     }
 
   template<> 
     numpunct<char>::~numpunct()
-    { }
+    { delete _M_data; }
       
 #ifdef _GLIBCPP_USE_WCHAR_T
   template<> 
@@ -59,15 +73,37 @@ namespace std
     numpunct<wchar_t>::_M_initialize_numpunct(__c_locale)
     {
       // "C" locale
-      _M_decimal_point = L'.';
-      _M_thousands_sep = L',';
-      _M_grouping = "";
-      _M_truename = L"true";
-      _M_falsename = L"false";
+      if (!_M_data)
+       _M_data = new __numpunct_cache<wchar_t>;
+
+      _M_data->_M_grouping = "";
+      _M_data->_M_use_grouping = false;
+      
+      _M_data->_M_decimal_point = L'.';
+      _M_data->_M_thousands_sep = L',';
+      
+      // Use ctype::widen code without the facet...
+      unsigned char uc;
+      for (size_t i = 0; i < __num_base::_S_oend; ++i)
+       {
+         uc = static_cast<unsigned char>(__num_base::_S_atoms_out[i]);
+         _M_data->_M_atoms_out[i] = btowc(uc);
+       }
+      _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t();
+      
+      for (size_t i = 0; i < __num_base::_S_iend; ++i)
+       {
+         uc = static_cast<unsigned char>(__num_base::_S_atoms_in[i]);
+         _M_data->_M_atoms_in[i] = btowc(uc);
+       }
+      _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t();
+      
+      _M_data->_M_truename = L"true";
+      _M_data->_M_falsename = L"false";
     }
 
   template<> 
     numpunct<wchar_t>::~numpunct()
-    { }
+    { delete _M_data; }
 #endif
 }
index 5b666ebe608d8b5dec2fd925dbb8c7b3f181566c..dd8c76b38f30bbdf91d46d5e0b0a3b5c743cf08b 100644 (file)
@@ -1,6 +1,6 @@
 // std::numpunct implementation details, GNU version -*- C++ -*-
 
-// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -42,70 +42,112 @@ namespace std
     void
     numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
     {
+      if (!_M_data)
+       _M_data = new __numpunct_cache<char>;
+
       if (!__cloc)
        {
          // "C" locale
-         _M_decimal_point = '.';
-         _M_thousands_sep = ',';
-         _M_grouping = "";
+         _M_data->_M_grouping = "";
+         _M_data->_M_use_grouping = false;
+
+         _M_data->_M_decimal_point = '.';
+         _M_data->_M_thousands_sep = ',';
+
+         for (size_t i = 0; i < __num_base::_S_oend; ++i)
+           _M_data->_M_atoms_out[i] = __num_base::_S_atoms_out[i];
+         _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t();
+
+         for (size_t i = 0; i < __num_base::_S_iend; ++i)
+           _M_data->_M_atoms_in[i] = __num_base::_S_atoms_in[i];
+         _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t();
        }
       else
        {
          // Named locale.
-         _M_decimal_point = *(__nl_langinfo_l(RADIXCHAR, __cloc));
-         _M_thousands_sep = *(__nl_langinfo_l(THOUSEP, __cloc));
-         // Check for NUL, which implies no grouping.
-         if (_M_thousands_sep == '\0')
-           _M_grouping = "";
+         _M_data->_M_decimal_point = *(__nl_langinfo_l(RADIXCHAR, __cloc));
+         _M_data->_M_thousands_sep = *(__nl_langinfo_l(THOUSEP, __cloc));
+
+         // Check for NULL, which implies no grouping.
+         if (_M_data->_M_thousands_sep == '\0')
+           _M_data->_M_grouping = "";
          else
-           _M_grouping = __nl_langinfo_l(GROUPING, __cloc);
+           _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
        }
       // NB: There is no way to extact this info from posix locales.
       // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
-      _M_truename = "true";
+      _M_data->_M_truename = "true";
       // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
-      _M_falsename = "false";
+      _M_data->_M_falsename = "false";
     }
  
   template<> 
     numpunct<char>::~numpunct()
-    { }
+    { delete _M_data; }
    
 #ifdef _GLIBCPP_USE_WCHAR_T
   template<> 
     void
     numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
     {
+      if (!_M_data)
+       _M_data = new __numpunct_cache<wchar_t>;
+
       if (!__cloc)
        {
          // "C" locale
-         _M_decimal_point = L'.';
-         _M_thousands_sep = L',';
-         _M_grouping = "";
+         _M_data->_M_grouping = "";
+         _M_data->_M_use_grouping = false;
+
+         _M_data->_M_decimal_point = L'.';
+         _M_data->_M_thousands_sep = L',';
+
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+         __c_locale __old = __uselocale(_S_c_locale);
+#endif
+         // Use ctype::widen code without the facet...
+         unsigned char uc;
+         for (size_t i = 0; i < __num_base::_S_oend; ++i)
+           {
+             uc = static_cast<unsigned char>(__num_base::_S_atoms_out[i]);
+             _M_data->_M_atoms_out[i] = btowc(uc);
+           }
+         _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t();
+
+         for (size_t i = 0; i < __num_base::_S_iend; ++i)
+           {
+             uc = static_cast<unsigned char>(__num_base::_S_atoms_in[i]);
+             _M_data->_M_atoms_in[i] = btowc(uc);
+           }
+         _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t();
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+         __uselocale(__old);
+#endif
        }
       else
        {
          // Named locale.
          union __s_and_w { const char *__s; unsigned int __w; } __u;
          __u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
-         _M_decimal_point = static_cast<wchar_t>(__u.__w);
+         _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
 
          __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
-         _M_thousands_sep = static_cast<wchar_t>(__u.__w);
-         if (_M_thousands_sep == L'\0')
-           _M_grouping = "";
+         _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
+
+         if (_M_data->_M_thousands_sep == L'\0')
+           _M_data->_M_grouping = "";
          else
-           _M_grouping = __nl_langinfo_l(GROUPING, __cloc);
+           _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
        }
       // NB: There is no way to extact this info from posix locales.
       // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
-      _M_truename = L"true";
+      _M_data->_M_truename = L"true";
       // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
-      _M_falsename = L"false";
+      _M_data->_M_falsename = L"false";
     }
 
   template<> 
     numpunct<wchar_t>::~numpunct()
-    { }
+    { delete _M_data; }
  #endif
 }
index cf2701effb21725b675789377ea4a25b951e54d6..54f34b599e521b5aa1af87b5e8b1efc9be7b610a 100644 (file)
@@ -138,12 +138,7 @@ namespace std
       ios_base::_M_init();
 
       // Cache locale data and specific facets used by iostreams.
-      if (!_M_locale_cache.get())
-       {
-         typedef __locale_cache<_CharT> __cache_t;
-         this->_M_locale_cache = auto_ptr<__locale_cache_base>(static_cast<__locale_cache_base*>(new __cache_t));
-         _M_cache_locale(_M_ios_locale);
-       }
+      _M_cache_locale(_M_ios_locale);
 
       // NB: The 27.4.4.1 Postconditions Table specifies requirements
       // after basic_ios::init() has been called. As part of this,
@@ -176,7 +171,6 @@ namespace std
        _M_num_put = &use_facet<__numput_type>(__loc); 
       if (__builtin_expect(has_facet<__numget_type>(__loc), true))
        _M_num_get = &use_facet<__numget_type>(__loc); 
-      static_cast<__locale_cache<_CharT>&>(_M_cache())._M_init(__loc); 
     }
 
   // Inhibit implicit instantiations for required instantiations,
index 37a02a43dddf956a686381c25fe3256f08d5f5f4..ef2f57ab0f89a0d8376e6b31ef2ea034767fa173 100644 (file)
@@ -146,8 +146,6 @@ namespace std
 
   enum _Ios_Seekdir { _S_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.
@@ -212,47 +210,65 @@ namespace std
      *  - floatfield
     */
     typedef _Ios_Fmtflags fmtflags;
+
     /// Insert/extract @c bool in alphabetic rather than numeric format.
     static const fmtflags boolalpha =   fmtflags(__ios_flags::_S_boolalpha);
+
     /// Converts integer input or generates integer output in decimal base.
     static const fmtflags dec =         fmtflags(__ios_flags::_S_dec);
+
     /// Generate floating-point output in fixed-point notation.
     static const fmtflags fixed =       fmtflags(__ios_flags::_S_fixed);
+
     /// Converts integer input or generates integer output in hexadecimal base.
     static const fmtflags hex =         fmtflags(__ios_flags::_S_hex);
+
     /// Adds fill characters at a designated internal point in certain
     /// generated output, or identical to @c right if no such point is
     /// designated.
     static const fmtflags internal =    fmtflags(__ios_flags::_S_internal);
+
     /// Adds fill characters on the right (final positions) of certain
     /// generated output.  (I.e., the thing you print is flush left.)
     static const fmtflags left =        fmtflags(__ios_flags::_S_left);
+
     /// Converts integer input or generates integer output in octal base.
     static const fmtflags oct =         fmtflags(__ios_flags::_S_oct);
+
     /// Adds fill characters on the left (initial positions) of certain
     /// generated output.  (I.e., the thing you print is flush right.)
     static const fmtflags right =       fmtflags(__ios_flags::_S_right);
+
     /// Generates floating-point output in scientific notation.
     static const fmtflags scientific =  fmtflags(__ios_flags::_S_scientific);
+
     /// Generates a prefix indicating the numeric base of generated integer
     /// output.
     static const fmtflags showbase =    fmtflags(__ios_flags::_S_showbase);
+
     /// Generates a decimal-point character unconditionally in generated
     /// floating-point output.
     static const fmtflags showpoint =   fmtflags(__ios_flags::_S_showpoint);
+
     /// Generates a + sign in non-negative generated numeric output.
     static const fmtflags showpos =     fmtflags(__ios_flags::_S_showpos);
+
     /// Skips leading white space before certain input operations.
     static const fmtflags skipws =      fmtflags(__ios_flags::_S_skipws);
+
     /// Flushes output after each output operation.
     static const fmtflags unitbuf =     fmtflags(__ios_flags::_S_unitbuf);
+
     /// Replaces certain lowercase letters with their uppercase equivalents
     /// in generated output.
     static const fmtflags uppercase =   fmtflags(__ios_flags::_S_uppercase);
+
     /// A mask of left|right|internal.  Useful for the 2-arg form of @c setf.
     static const fmtflags adjustfield = fmtflags(__ios_flags::_S_adjustfield);
+
     /// A mask of dec|oct|hex.  Useful for the 2-arg form of @c setf.
     static const fmtflags basefield =   fmtflags(__ios_flags::_S_basefield);
+
     /// A mask of scientific|fixed.  Useful for the 2-arg form of @c setf.
     static const fmtflags floatfield =  fmtflags(__ios_flags::_S_floatfield);
 
@@ -269,15 +285,19 @@ namespace std
      *  - goodbit
     */
     typedef _Ios_Iostate iostate;
+
     /// Indicates a loss of integrity in an input or output sequence (such
     /// as an irrecoverable read error from a file).
     static const iostate badbit =      iostate(__ios_flags::_S_badbit);
+
     /// Indicates that an input operation reached the end of an input sequence.
     static const iostate eofbit =      iostate(__ios_flags::_S_eofbit);
+
     /// Indicates that an input operation failed to read the expected
     /// characters, or that an output operation failed to generate the
     /// desired characters.
     static const iostate failbit =     iostate(__ios_flags::_S_failbit);
+
     /// Indicates all is well.
     static const iostate goodbit =     iostate(0);
 
@@ -296,19 +316,25 @@ namespace std
      *  - trunc
     */
     typedef _Ios_Openmode openmode;
+
     /// Seek to end before each write.
     static const openmode app =        openmode(__ios_flags::_S_app);
+
     /// Open and seek to end immediately after opening.
     static const openmode ate =        openmode(__ios_flags::_S_ate);
+
     /// Perform input and output in binary mode (as opposed to text mode).
     /// This is probably not what you think it is; see
     /// http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#3 and
     /// http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#7 for more.
     static const openmode binary =     openmode(__ios_flags::_S_bin);
+
     /// Open for input.  Default for @c ifstream and fstream.
     static const openmode in =         openmode(__ios_flags::_S_in);
+
     /// Open for output.  Default for @c ofstream and fstream.
     static const openmode out =        openmode(__ios_flags::_S_out);
+
     /// Open for input.  Default for @c ofstream.
     static const openmode trunc =      openmode(__ios_flags::_S_trunc);
 
@@ -323,10 +349,13 @@ namespace std
      *  - end, equivalent to @c SEEK_END in the C standard library.
     */
     typedef _Ios_Seekdir seekdir;
+
     /// Request a seek relative to the beginning of the stream.
     static const seekdir beg =                 seekdir(0);
+
     /// Request a seek relative to the current position within the sequence.
     static const seekdir cur =                 seekdir(SEEK_CUR);
+
     /// Request a seek relative to the current end of the sequence.
     static const seekdir end =                 seekdir(SEEK_END);
 
@@ -432,10 +461,6 @@ namespace std
     // Members for locale and locale caching.
     locale             _M_ios_locale;
 
-    // Cache of locale and facet data.
-    // Cast this to __locale_cache<_CharT>*
-    auto_ptr<__locale_cache_base>      _M_locale_cache;
-
     void 
     _M_init();
 
@@ -604,7 +629,7 @@ namespace std
 
     /**
      *  @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(),
@@ -613,6 +638,16 @@ namespace std
     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
     /**
      *  @doctodo
@@ -642,11 +677,6 @@ namespace std
       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 *_M_locale_cache; }
-
     // Destructor
     /**
      *  Destroys local storage and
index e7210f821fedc48b002333a6158c7ecb7b626bdb..cfc11493216a23c302fa27bae421257426a32148 100644 (file)
@@ -71,7 +71,11 @@ namespace std
     template<typename _Facet>
       friend const _Facet& 
       use_facet(const locale&);
-     
+
+    template<typename _Cache>
+      friend const _Cache&
+      __use_cache(const locale& __loc);
+   
     // Category values:
     // NB: Order must match _S_facet_categories definition in locale.cc
     static const category none         = 0;
@@ -141,6 +145,12 @@ namespace std
     // Current global locale
     static _Impl*      _S_global;  
 
+    // Names of underlying locale categories.  
+    // NB: locale::global() has to know how to modify all the
+    // underlying categories, not just the ones required by the C++
+    // standard.
+    static const char** _S_categories;
+
     // Number of standard categories. For C++, these categories are
     // collate, ctype, monetary, numeric, time, and messages. These
     // directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE,
@@ -153,12 +163,6 @@ namespace std
     // and LC_IDENTIFICATION.
     static const size_t _S_categories_size = 6 + _GLIBCPP_NUM_CATEGORIES;
 
-    // Names of underlying locale categories.  
-    // NB: locale::global() has to know how to modify all the
-    // underlying categories, not just the ones required by the C++
-    // standard.
-    static const char** _S_categories;
-
     explicit 
     locale(_Impl*) throw();
 
@@ -177,7 +181,107 @@ namespace std
   };
 
 
-  // Implementation object for locale 
+  // 22.1.1.1.2  Class locale::facet
+  class locale::facet
+  {
+  private:
+    friend class locale;
+    friend class locale::_Impl;
+
+    mutable _Atomic_word               _M_references;
+
+  protected:
+    // Contains data from the underlying "C" library for the classic locale.
+    static __c_locale                  _S_c_locale;
+
+    // String literal for the name of the classic locale.
+    static char                                _S_c_name[2];
+    
+    explicit 
+    facet(size_t __refs = 0) throw() : _M_references(__refs ? 1 : 0)
+    { }
+
+    virtual 
+    ~facet();
+
+    static void
+    _S_create_c_locale(__c_locale& __cloc, const char* __s, 
+                      __c_locale __old = 0);
+
+    static __c_locale
+    _S_clone_c_locale(__c_locale& __cloc);
+
+    static void
+    _S_destroy_c_locale(__c_locale& __cloc);
+
+  private:
+    inline void
+    _M_add_reference() const throw()
+    { __atomic_add(&_M_references, 1); }
+
+    inline void
+    _M_remove_reference() const throw()
+    {
+      if (__exchange_and_add(&_M_references, -1) == 1)
+       {
+         try 
+           { delete this; }  
+         catch (...) 
+           { }
+       }
+    }
+
+    facet(const facet&);  // Not defined.
+
+    void 
+    operator=(const facet&);  // Not defined.
+  };
+
+
+  // 22.1.1.1.3 Class locale::id
+  class locale::id
+  {
+  private:
+    friend class locale;
+    friend class locale::_Impl;
+
+    template<typename _Facet>
+      friend const _Facet&  
+      use_facet(const locale&);
+
+    template<typename _Facet>
+      friend bool           
+      has_facet(const locale&) throw ();
+
+    // NB: There is no accessor for _M_index because it may be used
+    // before the constructor is run; the effect of calling a member
+    // function (even an inline) would be undefined.
+    mutable size_t             _M_index;
+
+    // Last id number assigned.
+    static _Atomic_word        _S_highwater;   
+
+    void 
+    operator=(const id&);  // Not defined.
+
+    id(const id&);  // Not defined.
+
+  public:
+    // NB: This class is always a static data member, and thus can be
+    // counted on to be zero-initialized.
+    id() { }
+
+    inline size_t
+    _M_id() const
+    {
+      if (!_M_index)
+       _M_index = 1 + __exchange_and_add(&_S_highwater, 1);
+      return _M_index - 1;
+    }
+  };
+
+
+  // Implementation object for locale.
   class locale::_Impl
   {
   public:
@@ -185,19 +289,24 @@ namespace std
     friend class locale;
     friend class locale::facet;
 
+    template<typename _Facet>
+      friend bool  
+      has_facet(const locale&) throw();
+
     template<typename _Facet>
       friend const _Facet&  
       use_facet(const locale&);
 
-    template<typename _Facet>
-      friend bool  
-      has_facet(const locale&) throw();
+    template<typename _Cache>
+      friend const _Cache&
+      __use_cache(const locale& __loc);
 
   private:
     // Data Members.
     _Atomic_word                       _M_references;
     const facet**                      _M_facets;
     size_t                             _M_facets_size;
+    const facet**                      _M_caches;
     char**                             _M_names;
     static const locale::id* const     _S_id_ctype[];
     static const locale::id* const     _S_id_numeric[];
@@ -258,7 +367,14 @@ namespace std
     template<typename _Facet>
       inline void 
       _M_init_facet(_Facet* __facet)
-      { _M_install_facet(&_Facet::id, __facet);  }
+      { _M_install_facet(&_Facet::id, __facet); }
+
+    void
+    _M_install_cache(const facet* __cache, size_t __index)
+    { 
+      __cache->_M_add_reference();
+      _M_caches[__index] = __cache; 
+    }      
   };
 
   template<typename _Facet>
@@ -274,93 +390,6 @@ namespace std
          _M_impl->_M_names[__i] = __new;
        }
     }
-
-
-  // 22.1.1.1.2  Class locale::facet
-  class locale::facet
-  {
-  private:
-    friend class locale;
-    friend class locale::_Impl;
-
-    mutable _Atomic_word               _M_references;
-
-  protected:
-    // Contains data from the underlying "C" library for the classic locale.
-    static __c_locale                  _S_c_locale;
-
-    // String literal for the name of the classic locale.
-    static char                                _S_c_name[2];
-    
-    explicit 
-    facet(size_t __refs = 0) throw();
-
-    virtual 
-    ~facet();
-
-    static void
-    _S_create_c_locale(__c_locale& __cloc, const char* __s, 
-                      __c_locale __old = 0);
-
-    static __c_locale
-    _S_clone_c_locale(__c_locale& __cloc);
-
-    static void
-    _S_destroy_c_locale(__c_locale& __cloc);
-
-  private:
-    void 
-    _M_add_reference() const throw();
-
-    void 
-    _M_remove_reference() const throw();
-
-    facet(const facet&);  // Not defined.
-
-    void 
-    operator=(const facet&);  // Not defined.
-  };
-
-
-  // 22.1.1.1.3 Class locale::id
-  class locale::id
-  {
-  private:
-    friend class locale;
-    friend class locale::_Impl;
-    template<typename _Facet>
-      friend const _Facet&  
-      use_facet(const locale&);
-    template<typename _Facet>
-      friend bool           
-      has_facet(const locale&) throw ();
-
-    // NB: There is no accessor for _M_index because it may be used
-    // before the constructor is run; the effect of calling a member
-    // function (even an inline) would be undefined.
-    mutable size_t             _M_index;
-
-    // Last id number assigned.
-    static _Atomic_word        _S_highwater;   
-
-    void 
-    operator=(const id&);  // Not defined.
-
-    id(const id&);  // Not defined.
-
-  public:
-    // NB: This class is always a static data member, and thus can be
-    // counted on to be zero-initialized.
-    id();
-
-    inline size_t
-    _M_id() const
-    {
-      if (!_M_index)
-       _M_index = 1 + __exchange_and_add(&_S_highwater, 1);
-      return _M_index - 1;
-    }
-  };
 } // namespace std
 
 #endif
index a0060e8d59198bc0cce7dd0fe18df6c292b4828f..72141f1983eb20549f075fe58c8334dcf4f9025a 100644 (file)
@@ -574,6 +574,96 @@ namespace std
     _S_format_float(const ios_base& __io, char* __fptr, char __mod);
   };
 
+  template<typename _CharT>
+    struct __numpunct_cache : public locale::facet
+    {
+      // Types:
+      typedef _CharT                   char_type;
+
+      const char*                      _M_grouping;
+      bool                             _M_use_grouping;
+      const char_type*                         _M_truename;
+      const char_type*                 _M_falsename;
+      char_type                        _M_decimal_point;
+      char_type                        _M_thousands_sep;
+      
+      // A list of valid numeric literals for output: in 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_atoms_out[__num_base::_S_oend + 1];
+
+      // A list of valid numeric literals for output: in the standard
+      // "C" locale, this is "0123456789eEabcdfABCDF"
+      // This array contains the chars after having been passed
+      // through the current locale's ctype<_CharT>.widen().
+      _CharT                           _M_atoms_in[__num_base::_S_iend + 1];
+
+      bool                             _M_allocated;
+
+      __numpunct_cache(size_t __refs = 0) : locale::facet(__refs), 
+      _M_grouping(NULL), _M_use_grouping(false), _M_truename(NULL), 
+      _M_falsename(NULL), _M_decimal_point(char_type()), 
+      _M_thousands_sep(char_type()), _M_allocated(false)
+      { } 
+
+      ~__numpunct_cache();
+
+      void
+      _M_cache(const locale& __loc);
+    };
+
+  template<typename _CharT>
+    void
+    __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
+    {
+      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
+      string __grouping = __np.grouping();
+      char* __group = new char[__grouping.length() + 1];
+      __grouping.copy(__group, __grouping.length());
+      __group[__grouping.length()] = _CharT();
+      _M_grouping = __group;
+      
+      _M_use_grouping = __grouping.length() != 0 && __grouping.data()[0] != 0;
+
+      typedef basic_string<_CharT> __string_type;
+
+      __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_type __false = __np.falsename();
+      _CharT* __falsename = new _CharT[__false.length() + 1];
+      __false.copy(__falsename, __false.length());
+      __falsename[__false.length()] = _CharT(); 
+      _M_falsename = __falsename;
+            
+      _M_decimal_point = __np.decimal_point();
+      _M_thousands_sep = __np.thousands_sep();
+
+      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
+      __ct.widen(__num_base::_S_atoms_out, 
+                __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out);
+      _M_atoms_out[__num_base::_S_oend] = _CharT();
+      __ct.widen(__num_base::_S_atoms_in, 
+                __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in);
+      _M_atoms_in[__num_base::_S_iend] = _CharT();
+
+      _M_allocated = true;
+    }
+
+  template<typename _CharT>
+    __numpunct_cache<_CharT>::~__numpunct_cache()
+    {
+      if (_M_allocated)
+       {
+         delete [] _M_grouping;
+         delete [] _M_truename;
+         delete [] _M_falsename;
+       }
+    }
 
   template<typename _CharT>
     class numpunct : public locale::facet
@@ -582,23 +672,26 @@ namespace std
       // Types:
       typedef _CharT                   char_type;
       typedef basic_string<_CharT>     string_type;
+      typedef __numpunct_cache<_CharT>  __cache_type;
+
+    protected:
+      __cache_type*                    _M_data;
 
+    public:
       static locale::id                id;
 
-    private:
-      char_type                        _M_decimal_point;
-      char_type                        _M_thousands_sep;
-      const char*                      _M_grouping;
-      const char_type*                         _M_truename;
-      const char_type*                 _M_falsename;
+      explicit 
+      numpunct(size_t __refs = 0) : facet(__refs), _M_data(NULL)
+      { _M_initialize_numpunct(); }
 
-    public:
       explicit 
-      numpunct(size_t __refs = 0) : locale::facet(__refs) 
+      numpunct(__cache_type* __cache, size_t __refs = 0) 
+      : facet(__refs), _M_data(__cache)
       { _M_initialize_numpunct(); }
 
       explicit 
-      numpunct(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs) 
+      numpunct(__c_locale __cloc, size_t __refs = 0) 
+      : locale::facet(__refs), _M_data(NULL)
       { _M_initialize_numpunct(__cloc); }
 
       char_type    
@@ -627,23 +720,23 @@ namespace std
 
       virtual char_type    
       do_decimal_point() const
-      { return _M_decimal_point; }
+      { return _M_data->_M_decimal_point; }
 
       virtual char_type    
       do_thousands_sep() const
-      { return _M_thousands_sep; }
+      { return _M_data->_M_thousands_sep; }
 
       virtual string
       do_grouping() const
-      { return _M_grouping; }
+      { return _M_data->_M_grouping; }
 
       virtual string_type  
       do_truename() const
-      { return _M_truename; }
+      { return _M_data->_M_truename; }
 
       virtual string_type  
       do_falsename() const
-      { return _M_falsename; }
+      { return _M_data->_M_falsename; }
 
       // For use at construction time only.
       void 
@@ -1928,75 +2021,6 @@ namespace std
     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.  It is stored as an
-  // auto_ptr<__locale_cache_base> member of ios_base and directly
-  // accessed via a casting to the derived __locale_cache<_CharT> in
-  // parameterized facets.
-  // 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
-  {
-  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_oend];
-
-      // 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&);
-    };
 } // namespace std
 
 #endif
index 624018285d8e79347e5d18e0e4795b065db12406..5081591c1cbe0bd80e048a685328c06d04da888e 100644 (file)
@@ -86,6 +86,21 @@ namespace std
       return static_cast<const _Facet&>(*__facets[__i]);
     }
 
+  // Routine to access a cache for the facet.  If the cache didn't
+  // exist before, it gets constructed on the fly.
+  template<typename _Facet>
+    const _Facet&
+    __use_cache(const locale& __loc);
+
+  template<>
+    const __numpunct_cache<char>&
+    __use_cache(const locale& __loc);
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+  template<>
+    const __numpunct_cache<wchar_t>&
+    __use_cache(const locale& __loc);
+#endif
 
   // Stage 1: Determine a conversion specifier.
   template<typename _CharT, typename _InIter>
@@ -768,11 +783,12 @@ namespace std
       _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, 
                     _ValueT __v) const
       {
-       typedef __locale_cache<_CharT> __cache_type;
-       __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache());
-       _CharT* __lit = __lc._M_literals;
+       typedef typename numpunct<_CharT>::__cache_type  __cache_type;
+       const locale& __loc = __io._M_getloc();
+       const __cache_type& __lc = __use_cache<__cache_type>(__loc);
+       const _CharT* __lit = __lc._M_atoms_out;
 
-       // Long enough to hold hex, dec, and octal representations.
+       // Long enough to hold hex, dec, and octal representations.
        int __ilen = 4 * sizeof(_ValueT);
        _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
                                                             * __ilen));
@@ -872,8 +888,9 @@ namespace std
        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());
+       typedef typename numpunct<_CharT>::__cache_type  __cache_type;
+       const locale& __loc = __io._M_getloc();
+       const __cache_type& __lc = __use_cache<__cache_type>(__loc);
 
        // [22.2.2.2.2] Stage 1, numeric conversion to character.
        int __len;
@@ -918,7 +935,6 @@ namespace std
 
       // [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) 
@@ -974,8 +990,10 @@ namespace std
         }
       else
         {
-         typedef __locale_cache<_CharT> __cache_type;
-         __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache());
+         typedef typename numpunct<_CharT>::__cache_type  __cache_type;
+         const locale& __loc = __io._M_getloc();
+         const __cache_type& __lc = __use_cache<__cache_type>(__loc);
+
          typedef basic_string<_CharT>  __string_type;
          __string_type __name;
           if (__v)
@@ -2273,31 +2291,6 @@ namespace std
       return __s;
     }
 
-  // Generic definition, locale cache initialization.
-  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_oend, 
-                    _M_literals);
-       }
-    }
-
   // Inhibit implicit instantiations for required instantiations,
   // which are defined via explicit instantiations elsewhere.  
   // NB: This syntax is a GNU extension.
index a0220f1cd8e17b099844a30f0133f22dbfe4d4f5..6793a9b5da1becf2c64224135d6d6294137208b9 100644 (file)
@@ -127,6 +127,10 @@ namespace __gnu_cxx
   __attribute__ ((aligned(__alignof__(locale::facet*))));
   fake_facet_vec facet_vec[_GLIBCPP_NUM_FACETS];
 
+  typedef char fake_cache_vec[sizeof(locale::facet*)]
+  __attribute__ ((aligned(__alignof__(locale::facet*))));
+  fake_cache_vec cache_vec[_GLIBCPP_NUM_FACETS];
+
   typedef char fake_ctype_c[sizeof(std::ctype<char>)]
   __attribute__ ((aligned(__alignof__(std::ctype<char>))));
   fake_ctype_c ctype_c;
@@ -235,6 +239,17 @@ namespace __gnu_cxx
   fake_messages_w messages_w;
 #endif
 
+  // Storage for C locale caches
+  typedef char fake_locale_cache_c[sizeof(std::__numpunct_cache<char>)]
+  __attribute__ ((aligned(__alignof__(std::__numpunct_cache<char>))));
+  fake_locale_cache_c numpunct_cache_c;
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+  typedef char fake_locale_cache_w[sizeof(std::__numpunct_cache<wchar_t>)]
+  __attribute__ ((aligned(__alignof__(std::__numpunct_cache<wchar_t>))));
+  fake_locale_cache_w numpunct_cache_w;
+#endif
+
   // Globals for once-only runtime initialization of mutex objects.  This
   // allows static initialization of these objects on systems that need a
   // function call to initialize a mutex.  For example, see stl_threads.h.
index ee4fd24cc54a259bafb65637b500ed39ad9d9c9e..ee969b5d9c76dd38e39e94b06aa2f6d2bc5c5eae 100644 (file)
@@ -297,8 +297,8 @@ namespace std
     return __old;
   }
 
-  ios_base::ios_base() : _M_callbacks(0), _M_word_size(_S_local_word_size),
-                        _M_word(_M_local_word), _M_locale_cache(0)
+  ios_base::ios_base() 
+  : _M_callbacks(0), _M_word_size(_S_local_word_size), _M_word(_M_local_word)
   {
     // Do nothing: basic_ios::init() does it.  
     // NB: _M_callbacks and _M_word must be zero for non-initialized
index 73b028df1beff1b7b655d34df4b8aae3544cf49b..0936102a916c61da7d30e7e8fa9f68680a268577 100644 (file)
@@ -45,7 +45,6 @@ namespace std
   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<char>;
 
 #ifdef _GLIBCPP_USE_WCHAR_T
   template class moneypunct<wchar_t, false>;
@@ -54,11 +53,11 @@ namespace std
   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<wchar_t>;
 #endif
 
   // numpunct, numpunct_byname, num_get, and num_put
   template class numpunct<char>;
+  template struct __numpunct_cache<char>;
   template class numpunct_byname<char>;
   template class num_get<char, istreambuf_iterator<char> >;
   template class num_put<char, ostreambuf_iterator<char> >; 
@@ -102,6 +101,7 @@ namespace std
   
 #ifdef _GLIBCPP_USE_WCHAR_T
   template class numpunct<wchar_t>;
+  template struct __numpunct_cache<wchar_t>;
   template class numpunct_byname<wchar_t>;
   template class num_get<wchar_t, istreambuf_iterator<wchar_t> >;
   template class num_put<wchar_t, ostreambuf_iterator<wchar_t> >;
index db08de0feca792965b101bf8b02cef42fdfbadf4..7788a58419d21d08ddb0462c21744645e04bdfad 100644 (file)
@@ -449,30 +449,37 @@ namespace std
   locale::facet::
   ~facet() { }
 
-  locale::facet::
-  facet(size_t __refs) throw() : _M_references(__refs ? 1 : 0) 
-  { }
-
-  void  
-  locale::facet::
-  _M_add_reference() const throw()
-  { __atomic_add(&_M_references, 1); }
+  template<>
+    const __numpunct_cache<char>&
+    __use_cache(const locale& __loc)
+    {
+      size_t __i = numpunct<char>::id._M_id();
+      const locale::facet** __caches = __loc._M_impl->_M_caches;
+      if (!__caches[__i])
+       {
+         __numpunct_cache<char>* __tmp = new __numpunct_cache<char>;
+         __tmp->_M_cache(__loc);
+         __loc._M_impl->_M_install_cache(__tmp, __i);
+       }
+      return static_cast<const __numpunct_cache<char>&>(*__caches[__i]);
+    }
 
-  void  
-  locale::facet::
-  _M_remove_reference() const throw()
-  {
-    if (__exchange_and_add(&_M_references, -1) == 1)
-      {
-        try 
-         { delete this; }  
-       catch (...) 
-         { }
-      }
-  }
-  
-  locale::id::id() 
-  { }
+#ifdef _GLIBCPP_USE_WCHAR_T
+  template<>
+    const __numpunct_cache<wchar_t>&
+    __use_cache(const locale& __loc)
+    {
+      size_t __i = numpunct<wchar_t>::id._M_id();
+      const locale::facet** __caches = __loc._M_impl->_M_caches;
+      if (!__caches[__i])
+       {
+         __numpunct_cache<wchar_t>* __tmp = new __numpunct_cache<wchar_t>;
+         __tmp->_M_cache(__loc);
+         __loc._M_impl->_M_install_cache(__tmp, __i);
+       }
+      return static_cast<const __numpunct_cache<wchar_t>&>(*__caches[__i]);
+    }
+#endif
 
   // Definitions for static const data members of time_base
   template<> 
index c09900b628fcece62f26e5c61ebe85b72fd6843f..424bc64fec7349727ecbf0e0c32d781b8703e249 100644 (file)
@@ -69,6 +69,12 @@ namespace __gnu_cxx
   extern time_put<wchar_t>                     time_put_w;
   extern std::messages<wchar_t>                messages_w;
 #endif
+
+  extern locale::facet* cache_vec[_GLIBCPP_NUM_FACETS];
+  extern std::__numpunct_cache<char>           numpunct_cache_c;
+#ifdef  _GLIBCPP_USE_WCHAR_T
+  extern std::__numpunct_cache<wchar_t>                numpunct_cache_w;
+#endif
 } // namespace __gnu_cxx
 
 namespace std
@@ -83,6 +89,11 @@ namespace std
        _M_facets[__i]->_M_remove_reference();
     delete [] _M_facets;
 
+    for (size_t __i = 0; __i < _M_facets_size; ++__i)
+      if (_M_caches[__i])
+       _M_caches[__i]->_M_remove_reference(); 
+    delete [] _M_caches;
+
     for (size_t __i = 0; __i < _S_categories_size; ++__i)
       delete [] _M_names[__i];  
     delete [] _M_names;
@@ -91,7 +102,7 @@ namespace std
   // Clone existing _Impl object.
   locale::_Impl::
   _Impl(const _Impl& __imp, size_t __refs)
-  : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX
+  : _M_references(__refs), _M_facets_size(__imp._M_facets_size)
   {
     try
       { 
@@ -111,6 +122,22 @@ namespace std
          _M_facets[__i]->_M_add_reference();
       }
 
+    try 
+      {
+       _M_caches = new const facet*[_M_facets_size];
+      }
+    catch(...)
+      {
+       delete [] _M_caches;
+       __throw_exception_again;
+      }
+    for (size_t __i = 0; __i < _M_facets_size; ++__i)
+      {
+       _M_caches[__i] = __imp._M_caches[__i];
+       if (_M_caches[__i])
+         _M_caches[__i]->_M_add_reference(); 
+      }
+
     try 
       {
        _M_names = new char*[_S_categories_size];
@@ -131,10 +158,10 @@ namespace std
   // Construct named _Impl.
   locale::_Impl::
   _Impl(const char* __s, size_t __refs) 
-  : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) 
+  : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
   {
-    // Initialize the underlying locale model, which also checks
-    // to see if the given name is valid.
+    // Initialize the underlying locale model, which also checks to
+    // see if the given name is valid.
     __c_locale __cloc;
     locale::facet::_S_create_c_locale(__cloc, __s);
 
@@ -150,6 +177,18 @@ namespace std
        __throw_exception_again;
       }
 
+    try 
+      {
+       _M_caches = new const facet*[_M_facets_size];
+       for (size_t __i = 0; __i < _M_facets_size; ++__i)
+         _M_caches[__i] = 0;
+      }
+    catch(...)
+      {
+       delete [] _M_caches;
+       __throw_exception_again;
+      }
+
     // Name all the categories.
     try 
       {
@@ -235,6 +274,10 @@ namespace std
     for (size_t __i = 0; __i < _M_facets_size; ++__i)
       _M_facets[__i] = 0;
 
+    _M_caches = new (&cache_vec) const facet*[_M_facets_size];
+    for (size_t __i = 0; __i < _M_facets_size; ++__i)
+      _M_caches[__i] = 0;
+
     // Name all the categories.
     _M_names = new (&name_vec) char*[_S_categories_size];
     for (size_t __i = 0; __i < _S_categories_size; ++__i)
@@ -252,7 +295,12 @@ namespace std
     // destroyed.
     _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
     _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
-    _M_init_facet(new (&numpunct_c) numpunct<char>(1));
+
+    // Safe to cache this.
+    typedef __numpunct_cache<char> num_cache_c;
+    num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2);
+    _M_init_facet(new (&numpunct_c) numpunct<char>(__npc, 1));
+
     _M_init_facet(new (&num_get_c) num_get<char>(1));
     _M_init_facet(new (&num_put_c) num_put<char>(1));
     _M_init_facet(new (&collate_c) std::collate<char>(1));
@@ -264,10 +312,15 @@ namespace std
     _M_init_facet(new (&time_get_c) time_get<char>(1));
     _M_init_facet(new (&time_put_c) time_put<char>(1));
     _M_init_facet(new (&messages_c) std::messages<char>(1));   
+
 #ifdef  _GLIBCPP_USE_WCHAR_T
     _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
     _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
-    _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
+
+    typedef __numpunct_cache<wchar_t> num_cache_w;
+    num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2);
+    _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(__npw, 1));
+
     _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
     _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
     _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
@@ -280,6 +333,13 @@ namespace std
     _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
     _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
 #endif 
+
+    // This locale is safe to pre-cache, after all the facets have
+    // been installed.
+    _M_caches[numpunct<char>::id._M_id()] = __npc;
+#ifdef  _GLIBCPP_USE_WCHAR_T
+    _M_caches[numpunct<wchar_t>::id._M_id()] = __npw;
+#endif
   }
   
   void
@@ -336,18 +396,31 @@ namespace std
        // Check size of facet vector to ensure adequate room.
        if (__index > _M_facets_size - 1)
          {
-           const facet** __old = _M_facets;
-           const facet** __new;
            const size_t __new_size = __index + 4;
-           __new = new const facet*[__new_size]; 
+
+           // New facet array.
+           const facet** __oldf = _M_facets;
+           const facet** __newf;
+           __newf = new const facet*[__new_size]; 
+           for (size_t __i = 0; __i < _M_facets_size; ++__i)
+             __newf[__i] = _M_facets[__i];
+           for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
+             __newf[__i2] = 0;
+
+           // New cache array.
+           const facet** __oldc = _M_caches;
+           const facet** __newc;
+           __newc = new const facet*[__new_size]; 
            for (size_t __i = 0; __i < _M_facets_size; ++__i)
-             __new[__i] = _M_facets[__i];
+             __newc[__i] = _M_caches[__i];
            for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
-             __new[__i2] = 0;
+             __newc[__i2] = 0;
 
            _M_facets_size = __new_size;
-           _M_facets = __new;
-           delete [] __old;
+           _M_facets = __newf;
+           _M_caches = __newc;
+           delete [] __oldf;
+           delete [] __oldc;
          }
 
        __fp->_M_add_reference();
@@ -365,6 +438,21 @@ namespace std
            // swanky-fresh _Impl.
            _M_facets[__index] = __fp;
          }
+
+       // Ideally, it would be nice to only remove the caches that
+       // are now incorrect. However, some of the caches depend on
+       // multiple facets, and we only know about one facet
+       // here. It's no great loss: the first use of the new facet
+       // will create a new, correctly cached facet anyway.
+       for (size_t __i = 0; __i < _M_facets_size; ++__i)
+         {
+           const facet* __cpr = _M_caches[__i];
+           if (__cpr)
+             {
+               __cpr->_M_remove_reference();
+               _M_caches[__i] = 0;
+             }
+         }
       }
   }
 } // namespace std
index 7e138313b6f80403b2f8b88e950754aa659319c6..e6f9921b3686b49dd6c09f9465d1e252ad27f462 100644 (file)
@@ -41,5 +41,5 @@ void test01()
   io1 = io2;
 }
 // { dg-error "within this context" "" { target *-*-* } 41 } 
-// { dg-error "is private" "" { target *-*-* } 666 } 
+// { dg-error "is private" "" { target *-*-* } 696 } 
 // { dg-error "operator=" "" { target *-*-* } 0 } 
index 56531485c8b7df370b06b72e521837c3285b412e..5d77444b342a4230df6c6b636643e3e02771562a 100644 (file)
@@ -41,5 +41,5 @@ void test02()
   test_base io2 = io1; 
 }
 // { dg-error "within this context" "" { target *-*-* } 41 } 
-// { dg-error "is private" "" { target *-*-* } 663 } 
+// { dg-error "is private" "" { target *-*-* } 693 } 
 // { dg-error "copy constructor" "" { target *-*-* } 0 }