diff mbox

Do not copy std:call_once arguments (LWG 2442)

Message ID 20161012121615.GS2922@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Oct. 12, 2016, 12:16 p.m. UTC
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.
diff mbox

Patch

commit f4f65251fbf84547db29d04bfa60ffcf0540a188
Author: Jonathan Wakely <jwakely@redhat.com>
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