incubator-stdcxx-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Martin Sebor <mse...@gmail.com>
Subject Re: STDCXX-1056 [was: Re: STDCXX forks]
Date Wed, 05 Sep 2012 19:17:53 GMT
On 09/05/2012 12:40 PM, Liviu Nicoara wrote:
> On 09/05/12 14:09, Stefan Teleman wrote:
>> On Wed, Sep 5, 2012 at 10:52 AM, Martin Sebor <msebor@gmail.com> wrote:
>> [...]
>> OK so I did a little bit of testing, after looking at the *right*
>> __rw_guard class. :-)
>>
>> I changed the std::numpunct class thusly:
>> [...]
>> And then:
>>
>> template <class _CharT>
>> inline string numpunct<_CharT>::grouping () const
>> {
>> if (!(_C_flags & _RW::__rw_gr)) {
>>
>> _RWSTD_MT_GUARD (_C_object_mutex);
>>
>> // double-test here to avoid re-writing an already written string
>> if (!(_C_flags & _RW::__rw_gr)) {
>>
>> numpunct* const __self = _RWSTD_CONST_CAST (numpunct*, this);
>>
>> // [try to] get the grouping first (may throw)
>> // then set a flag to avoid future initializations
>> __self->_C_grouping = do_grouping ();
>> __self->_C_flags |= _RW::__rw_gr;
>>
>> }
>> }
>>
>> return _C_grouping;
>> }
>
> I am afraid this would be unsafe, too (if I said otherwise earlier I was
> wrong). The compiler might re-arrange the protected assignments, such
> that another thread sees a partially updated object, where the flags are
> updated and the string not. I don't think we're going to get away with
> this here without either a simpler and more inefficient top-level
> locking, or doing away completely with the lazy initialization. Thoughts?

You're right, there's still a problem. We didn't get the double
checked locking quite right. We need to prevent the reordering
both by the compiler and by the hardware so that the reader
doesn't get an out of date value of _C_grouping. Making the
members volatile and/or moving the body of the first if into
an out-of-line function should help with the compiler reordering
but we'll need a barrier to prevent the hardware from serving us
up stale data (i.e., letting T2 see the updated _C_flags but
a _C_grouping that's still being modified). Calling
pthread_mutex_unlock does insert a barrier, but the barrier
is only executed when both tests pass, and not when the first
one fails. We need the barrier in both cases. This seems like
it would get too ugly (and big) to put in an inline function.

Martin

>
> Liviu


Mime
View raw message