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?
Liviu