[PATCH] PR libstdc++/59439 optimize uses of classic ("C") std::locale
Jonathan Wakely
jwakely@redhat.com
Wed Oct 3 11:27:00 GMT 2018
On 26/09/18 17:17 +0100, Jonathan Wakely wrote:
>The global locale::_Impl that represents the "C" locale is never
>destroyed, so there is no need to keep track of reference count updates
>for that object. This greatly reduce contention between threads that
>refer to the classic locale. Since the global std::locale initially uses
>the classic locale, this benefits the common case for any code using the
>global locale, such as construction/destruction of iostream objects.
>
>All these updates are done inside libstdc++.so so there's no need to
>worry about users' objects having inlined old versions of the code which
>still update the reference count for the classic locale.
>
> PR libstdc++/59439
> * src/c++98/locale.cc (locale::locale(const locale&)): Bypass
> reference count updates for the classic locale.
> (locale::~locale()): Likewise. (locale::operator=(const
> locale&)): Likewise.
> * src/c++98/locale_init.cc (locale::locale()): Likewise.
> (locale::global(const locale&)): Likewise.
>
>Tested x86_64-linux, not committed yet.
>
>Does anybody see any problems with this change?
Committed to trunk.
>commit 131d4c26876a5a884fe4408deaf054e01ba90ffb
>Author: Jonathan Wakely <jwakely@redhat.com>
>Date: Wed Sep 26 16:34:42 2018 +0100
>
> PR libstdc++/59439 optimize uses of classic ("C") std::locale
>
> The global locale::_Impl that represents the "C" locale is never
> destroyed, so there is no need to keep track of reference count updates
> for that object. This greatly reduce contention between threads that
> refer to the classic locale. Since the global std::locale initially uses
> the classic locale, this benefits the common case for any code using the
> global locale, such as construction/destruction of iostream objects.
>
> All these updates are done inside libstdc++.so so there's no need to
> worry about users' objects having inlined old versions of the code which
> still update the reference count for the classic locale.
>
> PR libstdc++/59439
> * src/c++98/locale.cc (locale::locale(const locale&)): Bypass
> reference count updates for the classic locale.
> (locale::~locale()): Likewise. (locale::operator=(const
> locale&)): Likewise.
> * src/c++98/locale_init.cc (locale::locale()): Likewise.
> (locale::global(const locale&)): Likewise.
>
>diff --git a/libstdc++-v3/src/c++98/locale.cc b/libstdc++-v3/src/c++98/locale.cc
>index 148bf59658e..fe06d297039 100644
>--- a/libstdc++-v3/src/c++98/locale.cc
>+++ b/libstdc++-v3/src/c++98/locale.cc
>@@ -77,7 +77,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
> locale::locale(const locale& __other) throw()
> : _M_impl(__other._M_impl)
>- { _M_impl->_M_add_reference(); }
>+ {
>+ if (_M_impl != _S_classic)
>+ _M_impl->_M_add_reference();
>+ }
>
> // This is used to initialize global and classic locales, and
> // assumes that the _Impl objects are constructed correctly.
>@@ -86,7 +89,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> { }
>
> locale::~locale() throw()
>- { _M_impl->_M_remove_reference(); }
>+ {
>+ if (_M_impl != _S_classic)
>+ _M_impl->_M_remove_reference();
>+ }
>
> bool
> locale::operator==(const locale& __rhs) const throw()
>@@ -112,8 +118,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> const locale&
> locale::operator=(const locale& __other) throw()
> {
>- __other._M_impl->_M_add_reference();
>- _M_impl->_M_remove_reference();
>+ if (__other._M_impl != _S_classic)
>+ __other._M_impl->_M_add_reference();
>+ if (_M_impl != _S_classic)
>+ _M_impl->_M_remove_reference();
> _M_impl = __other._M_impl;
> return *this;
> }
>diff --git a/libstdc++-v3/src/c++98/locale_init.cc b/libstdc++-v3/src/c++98/locale_init.cc
>index c9078c015c3..b580a9f9d58 100644
>--- a/libstdc++-v3/src/c++98/locale_init.cc
>+++ b/libstdc++-v3/src/c++98/locale_init.cc
>@@ -257,9 +257,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> // fall back to lock protected access to both _S_global and
> // its reference count.
> _M_impl = _S_global;
>- if (_M_impl == _S_classic)
>- _M_impl->_M_add_reference();
>- else
>+ if (_M_impl != _S_classic)
> {
> __gnu_cxx::__scoped_lock sentry(get_locale_mutex());
> _S_global->_M_add_reference();
>@@ -275,7 +273,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> {
> __gnu_cxx::__scoped_lock sentry(get_locale_mutex());
> __old = _S_global;
>- __other._M_impl->_M_add_reference();
>+ if (__other._M_impl != _S_classic)
>+ __other._M_impl->_M_add_reference();
> _S_global = __other._M_impl;
> const string __other_name = __other.name();
> if (__other_name != "*")
>@@ -284,7 +283,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
> // Reference count sanity check: one reference removed for the
> // subsition of __other locale, one added by return-by-value. Net
>- // difference: zero. When the returned locale object's destrutor
>+ // difference: zero. When the returned locale object's destructor
> // is called, then the reference count is decremented and possibly
> // destroyed.
> return locale(__old);
More information about the Libstdc++
mailing list