[v3] Revised locale caches
Jerry Quinn
jlquinn@optonline.net
Thu Jun 19 01:58:00 GMT 2003
Benjamin Kosnik writes:
>
> I like your comments! They are pretty funny, as good comments should be.
We aim to please :-)
> This looks very interesting. It looks like locale::id should just be
> used in __locale_cache_base, huh?
It has to be part of the derived cache class so that
__locale_cache<char> gets a different id from __locale_cache<wchar_t>.
One thing I do want to know is whether the locking in
__locale_cache_base::id::_M_id is necessary, or for that matter, if it
has to be in the _M_id accessor in locale::id. Why doesn't the
constructor work there?
> I like that this avoids all the gross casting caused by the ios_base vs.
> basic_ios split. Big fan of this approach.
>
> Moving to per-facet cache instead of a monolithic one would be
> interesting, and would be the way to go I think. However, the
> initialization issues would be more complex.
Actually, initialization doesn't bother me as much as potentially
needing multiple caches in place of one. For example,
num_put::_M_convert_int uses ctype.widen(__num_base::_S_atoms_out),
and a couple of values from numpunct. So, either we may need to grab two
caches instead of one, or have copies of the values in multiple places
- where initialization really will start to be an issue.
> use_cache will have to be __use_cache.
Done.
> I almost have timers for the performance testsuite, and when I'm done
> with that I'll take a closer look at this, hopefully with memory and
> performance profiling.
Valgrind gives a clean report on printing to cout with no other
activity.
On performance/ofstream_insert_int.cc, using this cache
implementation, I get (debian linux on athlon 2100):
jlquinn@smaug:~/gcc/test$ time ./a.out
real 0m11.886s
user 0m11.480s
sys 0m0.360s
If I switch num_put<_CharT, _OutIter>::_M_convert_int to going through
the facet function calls, I get:
jlquinn@smaug:~/gcc/test$ time ./a.out
real 0m20.237s
user 0m19.790s
sys 0m0.430s
And of course, gcc 2.95 gives:
jlquinn@smaug:~/gcc/test$ g++-2.95 -O2 fstreamtest.cc
jlquinn@smaug:~/gcc/test$ time ./a.out
real 0m4.020s
user 0m3.640s
sys 0m0.300s
The previous patch had a couple of other minor goofs too.
Jerry
2003-06-18 Jerry Quinn <jlquinn@optonline.net>
* config/linker-map.gnu: Add __locale_cache*.
* include/bits/basic_ios.tcc (basic_ios::init,
basic_ios::_M_cache_locale): Remove cache initialization.
* include/bits/locale_classes.h
(locale,locale::_Impl): Befriend __use_cache.
(__locale_cache_base): Declare.
(locale::_Impl::_M_caches,locale::_Impl::_M_caches_size,
locale::_Impl::_S_static_caches_size,
locale::_Impl::_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): Befriend locale, locale::_Impl.
(__locale_cache_base::id): New class.
(__locale_cache): Befriend locale, locale::_Impl.
(__locale_cache::_M_id): New.
(__locale_cache::_M_truename): Change to char array.
(__locale_cache::_M_falsename): Change to char array.
(__locale_cache::_M_grouping): Change to char array.
(__locale_cache::__locale_cache(locale&)): New function.
(__locale_cache::_M_init(locale&,bool)): New function.
(__locale_cache::~__locale_cache): New function.
* include/bits/locale_facets.tcc (__use_cache): New function.
(num_put::_M_convert_int,_M_convert_float,do_put): Use it.
(__locale_cache::_M_init): Make raw char array copies of
numpunct fields.
(__locale_cache::_M_init(locale&,bool)): New.
* src/globals.cc (locale_cache_c, locale_cache_w): New.
* src/locale.cc (locale::_Impl::_S_static_caches): Define.
* src/localename.cc (locale_cache_c, locale_cache_w): Declare.
(locale::_Impl::~Impl): Destroy caches.
(locale::_Impl::Impl): Allocate and initialize cache storage.
Fill in static caches.
(__locale_cache::_M_id): Define.
(__locale_cache_base::id::_S_highwater): Define.
(__locale_cache_base::id::id): Define.
Index: config/linker-map.gnu
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/config/linker-map.gnu,v
retrieving revision 1.38
diff -c -r1.38 linker-map.gnu
*** config/linker-map.gnu 15 Jun 2003 23:24:00 -0000 1.38
--- config/linker-map.gnu 19 Jun 2003 01:44:57 -0000
***************
*** 55,61 ****
std::__num_base::_S_format_float*;
std::__num_base::_S_format_int*;
std::__num_base::_S_atoms_in;
! std::__num_base::_S_atoms_out
};
# Names not in an 'extern' block are mangled names.
--- 55,62 ----
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::__locale_cache*;
};
# Names not in an 'extern' block are mangled names.
Index: include/bits/basic_ios.tcc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/basic_ios.tcc,v
retrieving revision 1.21
diff -c -r1.21 basic_ios.tcc
*** include/bits/basic_ios.tcc 13 May 2003 20:13:14 -0000 1.21
--- include/bits/basic_ios.tcc 19 Jun 2003 01:44:57 -0000
***************
*** 138,149 ****
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);
! }
// NB: The 27.4.4.1 Postconditions Table specifies requirements
// after basic_ios::init() has been called. As part of this,
--- 138,144 ----
ios_base::_M_init();
// Cache locale data and specific facets used by iostreams.
! _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,182 ****
_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,
--- 171,176 ----
Index: include/bits/locale_classes.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/locale_classes.h,v
retrieving revision 1.6
diff -c -r1.6 locale_classes.h
*** include/bits/locale_classes.h 13 May 2003 20:13:14 -0000 1.6
--- include/bits/locale_classes.h 19 Jun 2003 01:44:57 -0000
***************
*** 72,77 ****
--- 72,81 ----
friend const _Facet&
use_facet(const locale&);
+ template<typename _Cache>
+ friend const _Cache&
+ __use_cache(const locale&);
+
// Category values:
// NB: Order must match _S_facet_categories definition in locale.cc
static const category none = 0;
***************
*** 176,181 ****
--- 180,186 ----
_M_coalesce(const locale& __base, const locale& __add, category __cat);
};
+ class __locale_cache_base;
// Implementation object for locale
class locale::_Impl
***************
*** 193,198 ****
--- 198,207 ----
friend bool
has_facet(const locale&) throw();
+ template<typename _Cache>
+ friend const _Cache&
+ __use_cache(const locale&);
+
private:
// Data Members.
_Atomic_word _M_references;
***************
*** 207,212 ****
--- 216,230 ----
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;
+ size_t _M_caches_size;
+
+ // For char and wchar_t
+ static const size_t _S_static_caches_size = 2;
+ static __locale_cache_base* _S_static_caches[];
+
inline void
_M_add_reference() throw()
{ __atomic_add(&_M_references, 1); }
***************
*** 259,264 ****
--- 277,310 ----
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. Storage is expanded to be >= __index.
+ __locale_cache_base*
+ _M_get_cache(size_t __index)
+ {
+ if (__index >= _M_caches_size)
+ {
+ __locale_cache_base** __tmp =
+ new __locale_cache_base*[__index + 4];
+ for (size_t __i = 0; __i < _M_caches_size; ++__i)
+ __tmp[__i] = _M_caches[__i];
+ for (size_t __i = _M_caches_size; __i < __index + 4; ++__i)
+ __tmp[__i] = 0;
+ // assert(_M_caches != _S_static_caches);
+ delete [] _M_caches;
+ _M_caches = __tmp;
+ _M_caches_size = __index + 4;
+ }
+ 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: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/locale_facets.h,v
retrieving revision 1.57
diff -c -r1.57 locale_facets.h
*** include/bits/locale_facets.h 7 May 2003 05:01:57 -0000 1.57
--- include/bits/locale_facets.h 19 Jun 2003 01:44:58 -0000
***************
*** 574,579 ****
--- 574,581 ----
_S_format_float(const ios_base& __io, char* __fptr, char __mod);
};
+ template<typename _CharT>
+ class __locale_cache;
template<typename _CharT>
class numpunct : public locale::facet
***************
*** 585,590 ****
--- 587,594 ----
static locale::id id;
+ friend class __locale_cache<_CharT>;
+
private:
char_type _M_decimal_point;
char_type _M_thousands_sep;
***************
*** 594,604 ****
public:
explicit
! numpunct(size_t __refs = 0) : locale::facet(__refs)
{ _M_initialize_numpunct(); }
explicit
! numpunct(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs)
{ _M_initialize_numpunct(__cloc); }
char_type
--- 598,608 ----
public:
explicit
! numpunct(size_t __refs = 0) : locale::facet(__refs)
{ _M_initialize_numpunct(); }
explicit
! numpunct(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs)
{ _M_initialize_numpunct(__cloc); }
char_type
***************
*** 1936,1946 ****
--- 1940,1986 ----
// 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
{
+ friend class std::locale::_Impl;
+ friend class locale;
+
+ public:
+ // Similar to locale::id.
+ class id
+ {
+ friend class locale::_Impl;
+
+ // 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;
+ }
+ };
public:
virtual
~__locale_cache_base() { }
***************
*** 1954,1959 ****
--- 1994,2010 ----
typedef char_traits<_CharT> traits_type;
typedef basic_string<_CharT> string_type;
+ friend class std::locale::_Impl;
+ friend class locale;
+
+ // XXX Using public because I can't for the life of me persuade
+ // g++ to give access to _M_id to locale::_Impl with friend
+ // decls. gcc bug?
+ public:
+
+ // Give each specialization a unique id.
+ static id _M_id;
+
public:
// Data Members:
***************
*** 1976,1983 ****
// 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
--- 2027,2034 ----
// 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
***************
*** 1985,1994 ****
// 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);
--- 2036,2051 ----
// If we are using numpunct's groupings, this is the current
// grouping string in effect (from numpunct::grouping()).
! const char* _M_grouping;
! __locale_cache() : _M_truename(0), _M_falsename(0),
! _M_use_grouping(false), _M_grouping(0)
! { }
!
! __locale_cache(const locale& __loc)
! : _M_truename(0), _M_falsename(0), _M_use_grouping(false),
! _M_grouping(0)
! { _M_init(__loc); }
__locale_cache&
operator=(const __locale_cache& __lc);
***************
*** 1996,2001 ****
--- 2053,2069 ----
// Make sure the cache is built before the first use.
void
_M_init(const locale&);
+
+ // For static initialization
+ void
+ _M_init(const locale&, bool);
+
+ ~__locale_cache()
+ {
+ delete [] _M_truename;
+ delete [] _M_falsename;
+ delete [] _M_grouping;
+ }
};
} // namespace std
Index: include/bits/locale_facets.tcc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/locale_facets.tcc,v
retrieving revision 1.99
diff -c -r1.99 locale_facets.tcc
*** include/bits/locale_facets.tcc 27 May 2003 21:14:49 -0000 1.99
--- include/bits/locale_facets.tcc 19 Jun 2003 01:44:59 -0000
***************
*** 86,91 ****
--- 86,106 ----
return static_cast<const _Facet&>(*__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 _Cache>
+ inline const _Cache&
+ __use_cache(const locale& __loc)
+ {
+ size_t __i = _Cache::_M_id._M_id();
+ __locale_cache_base* __cache = __loc._M_impl->_M_get_cache(__i);
+ if (!__cache)
+ {
+ __cache = new _Cache(__loc);
+ __loc._M_impl->_M_install_cache(__cache, __i);
+ }
+ return static_cast<const _Cache&>(*__cache);
+ }
// Stage 1: Determine a conversion specifier.
template<typename _CharT, typename _InIter>
***************
*** 769,778 ****
_ValueT __v) const
{
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);
_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __ilen));
--- 784,793 ----
_ValueT __v) const
{
typedef __locale_cache<_CharT> __cache_type;
! const __cache_type& __lc = __use_cache<__cache_type>(__io.getloc());
! const _CharT* __lit = __lc._M_literals;
! // Long enough to hold hex, dec, and octal representations.
int __ilen = 4 * sizeof(_ValueT);
_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __ilen));
***************
*** 873,880 ****
__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.
--- 888,894 ----
__prec = static_cast<streamsize>(6);
typedef __locale_cache<_CharT> __cache_type;
! const __cache_type& __lc = __use_cache<__cache_type>(__io.getloc());
// [22.2.2.2.2] Stage 1, numeric conversion to character.
int __len;
// Long enough for the max format spec.
***************
*** 975,981 ****
else
{
typedef __locale_cache<_CharT> __cache_type;
! __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache());
typedef basic_string<_CharT> __string_type;
__string_type __name;
if (__v)
--- 989,995 ----
else
{
typedef __locale_cache<_CharT> __cache_type;
! const __cache_type& __lc = __use_cache<__cache_type>(__io.getloc());
typedef basic_string<_CharT> __string_type;
__string_type __name;
if (__v)
***************
*** 2281,2293 ****
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))
{
--- 2295,2323 ----
if (__builtin_expect(has_facet<numpunct<_CharT> >(__loc), true))
{
const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
_M_thousands_sep = __np.thousands_sep();
_M_decimal_point = __np.decimal_point();
!
! string_type __false = __np.falsename();
! _CharT* __falsename = new _CharT[__false.length() + 1];
! __false.copy(__falsename, __false.length());
! __falsename[__false.length()] = _CharT(); // XXX is this right?
! _M_falsename = __falsename;
!
! string_type __true = __np.truename();
! _CharT* __truename = new _CharT[__true.length() + 1];
! __true.copy(__truename, __true.length());
! __truename[__true.length()] = _CharT(); // XXX
! _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 (__builtin_expect(has_facet<ctype<_CharT> >(__loc), true))
{
***************
*** 2296,2301 ****
--- 2326,2351 ----
__num_base::_S_atoms_out + __num_base::_S_oend,
_M_literals);
}
+ }
+
+ // Static locale cache initialization.
+ template<typename _CharT>
+ void
+ __locale_cache<_CharT>::_M_init(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_oend,
+ _M_literals);
}
// Inhibit implicit instantiations for required instantiations,
Index: src/globals.cc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/src/globals.cc,v
retrieving revision 1.17
diff -c -r1.17 globals.cc
*** src/globals.cc 11 May 2003 04:20:56 -0000 1.17
--- src/globals.cc 19 Jun 2003 01:44:59 -0000
***************
*** 33,38 ****
--- 33,39 ----
#include <locale>
#include <ext/stdio_filebuf.h>
#include <ext/stdio_sync_filebuf.h>
+ #include "bits/locale_facets.h"
// On AIX, and perhaps other systems, library initialization order is
// not guaranteed. For example, the static initializers for the main
***************
*** 233,238 ****
--- 234,250 ----
typedef char fake_messages_w[sizeof(messages<wchar_t>)]
__attribute__ ((aligned(__alignof__(messages<wchar_t>))));
fake_messages_w messages_w;
+ #endif
+
+ // Storage for static C locale caches
+ typedef char fake_locale_cache_c[sizeof(std::__locale_cache<char>)]
+ __attribute__ ((aligned(__alignof__(std::__locale_cache<char>))));
+ fake_locale_cache_c locale_cache_c;
+
+ #ifdef _GLIBCPP_USE_WCHAR_T
+ typedef char fake_locale_cache_w[sizeof(std::__locale_cache<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(std::__locale_cache<wchar_t>))));
+ fake_locale_cache_w locale_cache_w;
#endif
// Globals for once-only runtime initialization of mutex objects. This
Index: src/locale.cc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/src/locale.cc,v
retrieving revision 1.82
diff -c -r1.82 locale.cc
*** src/locale.cc 7 May 2003 05:01:59 -0000 1.82
--- src/locale.cc 19 Jun 2003 01:44:59 -0000
***************
*** 531,535 ****
--- 531,538 ----
*__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g';
*__fptr = '\0';
}
+
+ __locale_cache_base* std::locale::_Impl::_S_static_caches[2];
+
} // namespace std
Index: src/localename.cc
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/src/localename.cc,v
retrieving revision 1.39
diff -c -r1.39 localename.cc
*** src/localename.cc 28 Apr 2003 23:05:57 -0000 1.39
--- src/localename.cc 19 Jun 2003 01:44:59 -0000
***************
*** 69,74 ****
--- 69,79 ----
extern time_put<wchar_t> time_put_w;
extern std::messages<wchar_t> messages_w;
#endif
+
+ extern std::__locale_cache<char> locale_cache_c;
+ #ifdef _GLIBCPP_USE_WCHAR_T
+ extern std::__locale_cache<wchar_t> locale_cache_w;
+ #endif
} // namespace __gnu_cxx
namespace std
***************
*** 86,97 ****
for (size_t __i = 0; __i < _S_categories_size; ++__i)
delete [] _M_names[__i];
delete [] _M_names;
}
// Clone existing _Impl object.
locale::_Impl::
_Impl(const _Impl& __imp, size_t __refs)
! : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX
{
try
{
--- 91,110 ----
for (size_t __i = 0; __i < _S_categories_size; ++__i)
delete [] _M_names[__i];
delete [] _M_names;
+
+ // Clean up caches. No refcount for now.
+ if (_M_caches != _S_static_caches) {
+ for (size_t __i = 0; __i < _M_caches_size; ++__i)
+ delete _M_caches[__i];
+ delete [] _M_caches;
+ }
}
// Clone existing _Impl object.
locale::_Impl::
_Impl(const _Impl& __imp, size_t __refs)
! : _M_references(__refs), _M_facets_size(__imp._M_facets_size),
! _M_caches_size(__imp._M_caches_size)
{
try
{
***************
*** 126,137 ****
strcpy(__new, __imp._M_names[__i]);
_M_names[__i] = __new;
}
}
// Construct named _Impl.
locale::_Impl::
_Impl(const char* __s, size_t __refs)
! : _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.
--- 139,165 ----
strcpy(__new, __imp._M_names[__i]);
_M_names[__i] = __new;
}
+
+ // Allocate cache storage
+ try
+ {
+ _M_caches = new __locale_cache_base*[_M_caches_size];
+ }
+ catch(...)
+ {
+ delete [] _M_caches;
+ __throw_exception_again;
+ }
+
+ for (size_t __i = 0; __i < _M_caches_size; ++__i)
+ _M_caches[__i] = 0;
}
// Construct named _Impl.
locale::_Impl::
_Impl(const char* __s, size_t __refs)
! : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS),
! _M_caches_size(_S_static_caches_size)
{
// Initialize the underlying locale model, which also checks
// to see if the given name is valid.
***************
*** 218,229 ****
_M_init_facet(new std::messages<wchar_t>(__cloc, __s));
#endif
locale::facet::_S_destroy_c_locale(__cloc);
}
// Construct "C" _Impl.
locale::_Impl::
_Impl(facet**, size_t __refs, bool)
! : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
{
// Initialize the underlying locale model.
locale::facet::_S_c_name[0] = 'C';
--- 246,272 ----
_M_init_facet(new std::messages<wchar_t>(__cloc, __s));
#endif
locale::facet::_S_destroy_c_locale(__cloc);
+
+ // Create cache storage
+ try
+ {
+ _M_caches = new __locale_cache_base*[_M_caches_size];
+ }
+ catch(...)
+ {
+ delete [] _M_caches;
+ __throw_exception_again;
+ }
+
+ for (size_t __i = 0; __i < _M_caches_size; ++__i)
+ _M_caches[__i] = 0;
}
// Construct "C" _Impl.
locale::_Impl::
_Impl(facet**, size_t __refs, bool)
! : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS),
! _M_caches(_S_static_caches), _M_caches_size(_S_static_caches_size)
{
// Initialize the underlying locale model.
locale::facet::_S_c_name[0] = 'C';
***************
*** 280,285 ****
--- 323,345 ----
_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<char>* __lc = new (&locale_cache_c) __locale_cache<char>();
+ _M_caches[__locale_cache<char>::_M_id._M_id()] = __lc;
+ __lc->_M_init(ltmp, true);
+
+ #ifdef _GLIBCPP_USE_WCHAR_T
+ __locale_cache<wchar_t>* __wlc = new (&locale_cache_w) __locale_cache<wchar_t>();
+ _M_caches[__locale_cache<wchar_t>::_M_id._M_id()] = __wlc;
+ __wlc->_M_init(ltmp, true);
+ #endif
}
void
***************
*** 367,370 ****
--- 427,454 ----
}
}
}
+
+ // Static decl for __locale_cache::id
+ template<typename _CharT>
+ __locale_cache_base::id __locale_cache<_CharT>::_M_id;
+
+ // Definitions for static const data members of locale::id
+ _Atomic_word __locale_cache_base::id::_S_highwater; // init'd to 0 by linker
+
+ __locale_cache_base::id::id()
+ { }
+
+ template class __locale_cache<char>;
+ #ifdef _GLIBCPP_USE_WCHAR_T
+ template class __locale_cache<wchar_t>;
+ #endif
+
+ template
+ const __locale_cache<char>&
+ __use_cache<__locale_cache<char> >(const locale& __loc);
+
+ template
+ const __locale_cache<wchar_t>&
+ __use_cache<__locale_cache<wchar_t> >(const locale& __loc);
+
} // namespace std
More information about the Gcc-patches
mailing list