On 09/17/12 09:51, Stefan Teleman wrote:
On Mon, Sep 17, 2012 at 8:46 AM, Liviu Nicoara <nikko...@hates.ms> wrote:

In the meantime I would like to stress again that __rw_get_numpunct is
perfectly thread-safe and does not need extra locking for perfect
forwarding.

So, by removing the test for

           if (!(_C_flags & _RW::__rw_gr))

(or any other bitmask for that matter), the functions which were
thread-unsafe - and were exhibiting all the symptoms of a run-time
race condition -, magically became thread-safe?

I have looked *extensively* at the code in __rw_get_numpunct. It is
inherently thread-unsafe.

I mean to say that no extra locking is necessary when the public interface 
forwards and no caching is done.

In more detail: __rw_get_numpunct code is entered upon a call from the 
protected virtual interface. It calls facet _C_data member function which 
either returns objects constructed from previously-initialized POD data (in 
which case no locking is necessary), or it attempts to first initialize the 
facet data from the STDCXX database.

If the latter, the execution goes in the facet data initialization code which 
is appropriately synchronized, see this stack trace:

(gdb) bt
#0  __rw::__rw_facet::_C_get_data (this=0x6e10a0) at 
<srcdir>/stdcxx/branches/4.2.x/src/facet.cpp:179
#1  0x000000000043788b in __rw::__rw_facet::_C_data (this=0x6e10a0) at 
<srcdir>/stdcxx/branches/4.2.x/include/loc/_facet.h:194
#2  0x000000000044874f in __rw::__rw_get_numpunct (pfacet=0x6e10a0, flags=4) at 
<srcdir>/stdcxx/branches/4.2.x/src/punct.cpp:80
#3  0x0000000000449a14 in __rw::__rw_get_punct (pfacet=0x6e10a0, flags=4) at 
<srcdir>/stdcxx/branches/4.2.x/src/punct.cpp:578
#4  0x000000000041cecf in std::numpunct<char>::do_grouping (this=0x6e10a0) at 
<srcdir>/stdcxx/branches/4.2.x/include/loc/_numpunct.h:99
#5  0x000000000041bd31 in std::numpunct<char>::grouping (this=0x6e10a0) at 
<srcdir>/stdcxx/branches/4.2.x/include/loc/_numpunct.h:190
#6  0x00000000004036b8 in main (argc=2, argv=0x7fffffffe018) at 
<srcdir>/stdcxx/branches/4.2.x/tests/localization/s.cpp:29
(gdb)

When the above fails, the facet data has not been initialized, e.g., when there 
is no STDCXX locale database, or the name of the locale does not refer to a 
locale in STDCXX database. The __rw_get_numpunct function will attempt next to 
use libc and system locales, via the __rw_setlocale class, which again is 
properly synchronized and the scope of that lock extends to cover the facet 
data initialization. See this stack trace:

(gdb) bt
#0  __rw::__rw_setlocale::__rw_setlocale (this=0x7fffffffdd30, locname=0x6e112a 
"en_US.utf8", cat=6, nothrow=0) at 
<srcdir>/stdcxx/branches/4.2.x/src/setlocale.cpp:84
#1  0x0000000000448974 in __rw::__rw_get_numpunct (pfacet=0x6e10a0, flags=4) at 
<srcdir>/stdcxx/branches/4.2.x/src/punct.cpp:134
#2  0x0000000000449a14 in __rw::__rw_get_punct (pfacet=0x6e10a0, flags=4) at 
<srcdir>/stdcxx/branches/4.2.x/src/punct.cpp:578
#3  0x000000000041cecf in std::numpunct<char>::do_grouping (this=0x6e10a0) at 
<srcdir>/stdcxx/branches/4.2.x/include/loc/_numpunct.h:99
#4  0x000000000041bd31 in std::numpunct<char>::grouping (this=0x6e10a0) at 
<srcdir>/stdcxx/branches/4.2.x/include/loc/_numpunct.h:190
#5  0x00000000004036b8 in main (argc=2, argv=0x7fffffffe018) at 
<srcdir>/stdcxx/branches/4.2.x/tests/localization/s.cpp:29

I hope you agree that this synchronization is sufficient for the facet 
initialization and reading of facet data.

Thanks.

Liviu

Reply via email to