On 09/05/12 14:09, Stefan Teleman wrote:
On Wed, Sep 5, 2012 at 10:52 AM, Martin Sebor <[email protected]> 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
