On 09/06/2012 09:58 AM, Stefan Teleman wrote:
On Thu, Sep 6, 2012 at 9:16 AM, Liviu Nicoara<nikko...@hates.ms>  wrote:

I think Stefan is referring to adding a mutex member variable to the facet
in question and breaking binary compatibility. If that is the case I have
confused things when I suggested exactly that, earlier. A cursory read
through the __rw_facet source shows that inherits from __rw_synchronized in
MT builds, therefore each facet carries its own mutex member.

On 09/05/12 23:51, Martin Sebor wrote:
We don't need to add a new mutex -- we can use the __rw_facet
member for the locking. Or did you mean something else?

A possible implementation using the __rw_facet mutex could look like this:

template<class _CharT>
inline string numpunct<_CharT>::grouping () const
{
     if (!(_C_flags&  _RW::__rw_gr)) {

         numpunct* const __self = _RWSTD_CONST_CAST (numpunct*, this);

         _RWSTD_MT_GUARD (__self->_C_mutex);

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

             // [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;
}

Except that it will not work. Because the __rw_facet mutex member is
being locked  in file ../src/facet.cpp in function
__rw_facet::_C_manage at line 366:

// acquire lock
_RWSTD_MT_STATIC_GUARD (_RW::__rw_facet);

This locks a different mutex, one unrelated to __rw_facet::_C_mutex.

Look at the implementation of _RWSTD_MT_STATIC_GUARD() in rw/_defs.h:

  #  define _RWSTD_MT_STATIC_GUARD(type)                         \
            typedef _RW::__rw_type<type,__LINE__> _UniqueType;   \
            _RWSTD_MT_CLASS_GUARD (_UniqueType)

  #  define _RWSTD_MT_CLASS_GUARD(type)                           \
            _RWSTD_MT_GUARD (_RW::__rw_get_static_mutex ((type*)0))

and then at __rw_get_static_mutex in rw/_mutex.h. It gets a static
("global") mutex from a "mutex factory" via template instantiation:

  __rw_static_mutex<__rw_facet>::_C_mutex;


This will deadlock because this is the mutex already locked by
std::numpunct<T>::grouping().

I've already tested this with 3 compilers, and, it does indeed deadlock.

Something else must be locking the mutex then. I quickly looked
at __rw_get_punct (and __rw_get_numpunct) in punct.cpp but I
couldn't find any signs of the mutex being locked there. The
only thing I see being locked there is the global C locale. If
it's not the callee it has to be the caller.


So yes, I did indeed mean something different. I meant adding another
mutex data member to the numpunct class.

We can't (and shouldn't need to) add one. We need to be able to
make do with the existing member. That's what it's there for.

Martin


--Stefan


Reply via email to