This is the mail archive of the 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/ 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&
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;
// 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;
// Just call destructor, so that locale_impl_c's memory is
// not deallocated via a call to delete.
if (__tmp_S_classic)
_S_classic = _S_global = 0;
return c_locale;

Andrew Pollard - Senior Software Engineer (APF)
Brooks-PRI Automation - Planning and Logistics Solutions
Email: - 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]