This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: libstdc++/7445: poor performance of std::locale::classic() inmulti-threaded applications



Hi There,

The recent checkin to libstdc++--v3/src/locale.cc that went into V3.2 (and the trunk) isn't really correct - it probably works, but there is a problem
if two threads call the method at the same time.

There was a reason that I locked the entire method, so that _S_classic is
guaranteed to only be set once. With the code right now, there are a couple
of problems....

a) If two threads call the method at the same time when _S_classic isn't set,
one of them will obtain the lock, construct the internals, set _S_classic
and then exit, at which point the 2nd will get the lock and reconstruct the
internals and set _S_classic again.

b) If one thread is in the process of constructing the internals and setting
_S_classic (and it has done the _S_classic assignment, but not yet
constructed the c_locate object), a 2nd thread calling the method will
immediately return the not yet constructed c_locale object.

I think these two problems can be worked around.

a) Have a 2nd check for _S_classic after the auto lock, to handle the above
case "a"
b) set _S_classic as the last thing that the method does to handle the above
case "b"

A tentative version of this follows (assuming pointer reads and writes are
atomic - which if they aren't this is the least of the potential problems :-)

----------------------------------------------------------------------------------
const locale&
locale::classic()
{
if (!_S_classic)
{
static _STL_mutex_lock __lock __STL_MUTEX_INITIALIZER;
_STL_auto_lock __auto(__lock);

if (!_S_classic)
{
locale::_Impl* __tmp_S_classic = 0;
try
{
// 26 Standard facets, 2 references.
// One reference for _M_classic, one for _M_global
facet** f = new(&facet_vec) facet*[_GLIBCPP_NUM_FACETS];
for (size_t __i = 0; __i < _GLIBCPP_NUM_FACETS; ++__i)
f[__i] = 0;

__tmp_S_classic = new (&c_locale_impl) _Impl(f, 2, true);
new (&c_locale) locale(__tmp_S_classic);
_S_classic = _S_global = __tmp_S_classic;
}
catch(...)
{
// Just call destructor, so that locale_impl_c's memory is
// not deallocated via a call to delete.
if (__tmp_S_classic)
__tmp_S_classic->~_Impl();
_S_classic = _S_global = 0;
__throw_exception_again;
}
}
}
return c_locale;
}
----------------------------------------------------------------------------------

Andrew.
--
Andrew Pollard - Senior Software Engineer (APF)
Brooks-PRI Automation - Planning and Logistics Solutions
Email: Andrew.Pollard@brooks-pri.com - Tel: +44 (0)118 9215603


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