[v3] locale cache PR 7076,8761
Jerry Quinn
jlquinn@optonline.net
Sat Jul 5 04:32:00 GMT 2003
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();
More information about the Libstdc++
mailing list