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 <mse...@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

Reply via email to