On 12/10/16 12:22 +0100, Jonathan Wakely wrote:
This replaces the use of std::__bind_simple by direct calls to std::__invoke so that the arguments are not decay-copied.* doc/xml/manual/intro.xml: Document LWG 2442 status. * include/std/mutex [_GLIBCXX_HAVE_TLS] (__once_call_impl): Remove. [_GLIBCXX_HAVE_TLS] (_Once_call): Declare primary template and define partial specialization to unpack args and forward to std::invoke. (call_once) [_GLIBCXX_HAVE_TLS]: Use forward_as_tuple and _Once_call instead of __bind_simple and __once_call_impl. (call_once) [!_GLIBCXX_HAVE_TLS]: Use __invoke instead of __bind_simple. * testsuite/30_threads/call_once/dr2442.cc: New test. Tested powerpc64le-linux, committed to trunk.
I don't know why I over-complicated it by packing and unpacking the args in a tuple, this is much simpler, and makes the TLS and non-TLS implementations more similar. Tested powerpc64le-linux, committed to trunk.
commit f4f65251fbf84547db29d04bfa60ffcf0540a188 Author: Jonathan Wakely <[email protected]> Date: Wed Oct 12 12:30:35 2016 +0100 Simplify std::call_once implementation * include/std/mutex [_GLIBCXX_HAVE_TLS] (_Once_call): Remove. (call_once) [_GLIBCXX_HAVE_TLS]: Simplify by removing _Once_call. diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex index 4c6f036..e90006f 100644 --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -579,21 +579,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef _GLIBCXX_HAVE_TLS extern __thread void* __once_callable; extern __thread void (*__once_call)(); - - template<typename _Tuple, typename _IndexSeq - = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type> - struct _Once_call; - - template<typename _Tuple, size_t... _Ind> - struct _Once_call<_Tuple, _Index_tuple<_Ind...>> - { - static void - _S_call() - { - auto& __f_args = *static_cast<_Tuple*>(__once_callable); - std::__invoke(std::get<_Ind>(std::move(__f_args))...); - } - }; #else extern function<void()> __once_functor; @@ -613,17 +598,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2442. call_once() shouldn't DECAY_COPY() -#ifdef _GLIBCXX_HAVE_TLS - auto __f_args = std::forward_as_tuple( - std::forward<_Callable>(__f), std::forward<_Args>(__args)...); - __once_callable = std::__addressof(__f_args); - __once_call = _Once_call<decltype(__f_args)>::_S_call; -#else - unique_lock<mutex> __functor_lock(__get_once_mutex()); - __once_functor = [&] { + auto __callable = [&] { std::__invoke(std::forward<_Callable>(__f), std::forward<_Args>(__args)...); }; +#ifdef _GLIBCXX_HAVE_TLS + __once_callable = std::__addressof(__callable); + __once_call = []{ (*(decltype(__callable)*)__once_callable)(); }; +#else + unique_lock<mutex> __functor_lock(__get_once_mutex()); + __once_functor = __callable; __set_once_functor_lock_ptr(&__functor_lock); #endif
