This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: libstdc++/7445: poor performance of std::locale::classic() in multi-threaded applications


> I still think the two problems I mentioned are still there even with
> this version of the patch, namely
> 
> a) Two threads can enter the method at once, the first will get the
>     lock, set up _S_classic, etc, and release the lock, then the 2nd
>     will do exactly the same things again.
>     This can be fixed by checking _S_classic again after the auto lock
> 
> b) If a second thread enters while another is in the process of
> setting
>     up _S_classic, ie it has assigned _S_classic, but not initialised
>     c_locale, the 2nd thread will return the unconstructed c_locale
>     object.
>     This can be fixed by setting _S_classic as the last thing in the
>     method
> 
> I think the location of the static mutex doesn't matter.
> 
> So, again, I think the entire routine needs to be changed to something
> like this... (comments included to indicate reasoning...)

I'm not excited by this patch. There has got to be a better way. Loren,
can you commet on this? I should have just waited for you before I
checked this in anyway. 

>    const locale&
>    locale::classic()
>    {
>      // libstdc++/7445 - Optimisation to avoid the auto-lock once the
>      initial// creation has been done
>      if (_S_classic)
>        return c_locale;

weak


>      static _STL_mutex_lock __lock __STL_MUTEX_INITIALIZER;
>      _STL_auto_lock __auto(__lock);
> 
>      // In case multiple threads call locale::classic() at the same
>      time with// _S_classic unset, check if another thread might have
>      already done the// work
>      if (_S_classic)
>        return c_locale;

really weak


>      locale::_Impl* __tmp_S_classic = 0;
>      try
>        {
>          // 26 Standard facets, 2 references.
>          // One reference for _M_classic, one for _M_global
>          facet** f = new(&facet_vec) facet*[_GLIBCPP_NUM_FACETS];
>          for (size_t __i = 0; __i < _GLIBCPP_NUM_FACETS; ++__i)
>            f[__i] = 0;
> 
>          __tmp_S_classic = new (&c_locale_impl) _Impl(f, 2, true);
>          new (&c_locale) locale(__tmp_S_classic);
> 
>          // Set _S_classic last when we know we have done all the
>          initialisation_S_classic = _S_global = __tmp_S_classic;
>        }
>      catch(...)
>        {
>          // Just call destructor, so that locale_impl_c's memory is
>          // not deallocated via a call to delete.
>          if (tmp_S_classic)
>            tmp_S_classic->~_Impl();
>          _S_classic = _S_global = 0;
>          __throw_exception_again;
>        }
>      return c_locale;
>    }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]