Replace __bind_simple with std::thread::__make_invoker
authorJonathan Wakely <jwakely@redhat.com>
Thu, 13 Oct 2016 10:37:13 +0000 (11:37 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 13 Oct 2016 10:37:13 +0000 (11:37 +0100)
* include/std/functional (_Bind_simple, _Bind_simple_helper)
(__bind_simple): Remove.
* include/std/future: Include <bits/invoke.h> instead of <functional>.
(__future_base::_Task_state::_M_run)
(__future_base::_Task_state::_M_run_delayed): Use lambda expressions
instead of __bind_simple.
(__future_base::_Task_state::_S_maybe_wrap_ref): Remove.
(async): Use thread::__make_invoker instead of __bind_simple.
* include/std/thread: Include <tuple> and <bits/invoke.h> instead of
<functional>.
(thread::_Invoker, thread::__make_invoker): Define helpers to do
INVOKE(DECAY_COPY(f), DECAY_COPY(args)...).

From-SVN: r241093

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/functional
libstdc++-v3/include/std/future
libstdc++-v3/include/std/thread

index ffb78ea2f919152c5500633c31adda78b011986a..d08a8b1d96660df33e3908ebd779f5303641c178 100644 (file)
@@ -1,5 +1,18 @@
 2016-10-13  Jonathan Wakely  <jwakely@redhat.com>
 
+       * include/std/functional (_Bind_simple, _Bind_simple_helper)
+       (__bind_simple): Remove.
+       * include/std/future: Include <bits/invoke.h> instead of <functional>.
+       (__future_base::_Task_state::_M_run)
+       (__future_base::_Task_state::_M_run_delayed): Use lambda expressions
+       instead of __bind_simple.
+       (__future_base::_Task_state::_S_maybe_wrap_ref): Remove.
+       (async): Use thread::__make_invoker instead of __bind_simple.
+       * include/std/thread: Include <tuple> and <bits/invoke.h> instead of
+       <functional>.
+       (thread::_Invoker, thread::__make_invoker): Define helpers to do
+       INVOKE(DECAY_COPY(f), DECAY_COPY(args)...).
+
        * include/std/functional (_Not_fn): Make exception specifications
        depend on whether negating the result can throw.
        * testsuite/20_util/not_fn/1.cc: Move to ...
index 58134b7a0e5eeb864417fd2709df3566a09f5cb5..38770336c04bc8c33290528b0c6e33e19fd48eab 100644 (file)
@@ -1300,69 +1300,6 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
                           std::forward<_BoundArgs>(__args)...);
     }
 
-  template<typename _Signature>
-    struct _Bind_simple;
-
-  template<typename _Callable, typename... _Args>
-    struct _Bind_simple<_Callable(_Args...)>
-    {
-      typedef typename result_of<_Callable(_Args...)>::type result_type;
-
-      template<typename _Tp, typename... _Up>
-        explicit
-        _Bind_simple(_Tp&& __f, _Up&&... __args)
-        : _M_bound(std::forward<_Tp>(__f), std::forward<_Up>(__args)...)
-        { }
-
-      _Bind_simple(const _Bind_simple&) = default;
-      _Bind_simple(_Bind_simple&&) = default;
-
-      result_type
-      operator()()
-      {
-        typedef typename _Build_index_tuple<sizeof...(_Args)>::__type _Indices;
-        return _M_invoke(_Indices());
-      }
-
-    private:
-      template<std::size_t... _Indices>
-        typename result_of<_Callable(_Args...)>::type
-        _M_invoke(_Index_tuple<_Indices...>)
-        {
-         // std::bind always forwards bound arguments as lvalues,
-         // but this type can call functions which only accept rvalues.
-          return std::forward<_Callable>(std::get<0>(_M_bound))(
-              std::forward<_Args>(std::get<_Indices+1>(_M_bound))...);
-        }
-
-      std::tuple<_Callable, _Args...> _M_bound;
-    };
-
-  template<typename _Func, typename... _BoundArgs>
-    struct _Bind_simple_helper
-    : _Bind_check_arity<typename decay<_Func>::type, _BoundArgs...>
-    {
-      typedef _Maybe_wrap_member_pointer<typename decay<_Func>::type>
-        __maybe_type;
-      typedef typename __maybe_type::type __func_type;
-      typedef _Bind_simple<__func_type(typename decay<_BoundArgs>::type...)>
-               __type;
-    };
-
-  // Simplified version of std::bind for internal use, without support for
-  // unbound arguments, placeholders or nested bind expressions.
-  template<typename _Callable, typename... _Args>
-    typename _Bind_simple_helper<_Callable, _Args...>::__type
-    __bind_simple(_Callable&& __callable, _Args&&... __args)
-    {
-      typedef _Bind_simple_helper<_Callable, _Args...> __helper_type;
-      typedef typename __helper_type::__maybe_type __maybe_type;
-      typedef typename __helper_type::__type __result_type;
-      return __result_type(
-          __maybe_type::__do_wrap( std::forward<_Callable>(__callable)),
-          std::forward<_Args>(__args)...);
-    }
-
   /**
    *  @brief Exception class thrown when class template function's
    *  operator() is called with an empty target.
index aa866c5906a7f0c58c33508f792eec5067dfb32b..fffbdbb70520e11c13922291b573646fcf87c5ff 100644 (file)
@@ -35,7 +35,6 @@
 # include <bits/c++0x_warning.h>
 #else
 
-#include <functional>
 #include <mutex>
 #include <thread>
 #include <condition_variable>
@@ -43,6 +42,7 @@
 #include <atomic>
 #include <bits/atomic_futex.h>
 #include <bits/functexcept.h>
+#include <bits/invoke.h>
 #include <bits/unique_ptr.h>
 #include <bits/shared_ptr.h>
 #include <bits/uses_allocator.h>
@@ -1403,18 +1403,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       virtual void
       _M_run(_Args&&... __args)
       {
-       // bound arguments decay so wrap lvalue references
-       auto __boundfn = std::__bind_simple(std::ref(_M_impl._M_fn),
-           _S_maybe_wrap_ref(std::forward<_Args>(__args))...);
+       auto __boundfn = [&] () -> typename result_of<_Fn(_Args&&...)>::type {
+           return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...);
+       };
        this->_M_set_result(_S_task_setter(this->_M_result, __boundfn));
       }
 
       virtual void
       _M_run_delayed(_Args&&... __args, weak_ptr<_State_base> __self)
       {
-       // bound arguments decay so wrap lvalue references
-       auto __boundfn = std::__bind_simple(std::ref(_M_impl._M_fn),
-           _S_maybe_wrap_ref(std::forward<_Args>(__args))...);
+       auto __boundfn = [&] () -> typename result_of<_Fn(_Args&&...)>::type {
+           return std::__invoke(_M_impl._M_fn, std::forward<_Args>(__args)...);
+       };
        this->_M_set_delayed_result(_S_task_setter(this->_M_result, __boundfn),
                                    std::move(__self));
       }
@@ -1422,17 +1422,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       virtual shared_ptr<_Task_state_base<_Res(_Args...)>>
       _M_reset();
 
-      template<typename _Tp>
-       static reference_wrapper<_Tp>
-       _S_maybe_wrap_ref(_Tp& __t)
-       { return std::ref(__t); }
-
-      template<typename _Tp>
-       static
-       typename enable_if<!is_lvalue_reference<_Tp>::value, _Tp>::type&&
-       _S_maybe_wrap_ref(_Tp&& __t)
-       { return std::forward<_Tp>(__t); }
-
       struct _Impl : _Alloc
       {
        template<typename _Fn2>
@@ -1713,8 +1702,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        {
          __try
            {
-             __state = __future_base::_S_make_async_state(std::__bind_simple(
-                 std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
+             __state = __future_base::_S_make_async_state(
+                 std::thread::__make_invoker(std::forward<_Fn>(__fn),
+                                             std::forward<_Args>(__args)...)
+                 );
            }
 #if __cpp_exceptions
          catch(const system_error& __e)
@@ -1727,8 +1718,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
       if (!__state)
        {
-         __state = __future_base::_S_make_deferred_state(std::__bind_simple(
-              std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
+         __state = __future_base::_S_make_deferred_state(
+             std::thread::__make_invoker(std::forward<_Fn>(__fn),
+                                         std::forward<_Args>(__args)...));
        }
       return future<__async_result_of<_Fn, _Args...>>(__state);
     }
index 7e185d310dd18abab2b9e350c3f6135f96e103da..7a3c4078cc123c5df28c8621112642e0f7b4072f 100644 (file)
 #else
 
 #include <chrono>
-#include <functional>
 #include <memory>
+#include <tuple>
 #include <cerrno>
 #include <bits/functexcept.h>
 #include <bits/functional_hash.h>
+#include <bits/invoke.h>
 #include <bits/gthr.h>
 
 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
@@ -122,8 +123,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        auto __depend = nullptr;
 #endif
         _M_start_thread(_S_make_state(
-             std::__bind_simple(std::forward<_Callable>(__f),
-                                std::forward<_Args>(__args)...)),
+             __make_invoker(std::forward<_Callable>(__f),
+                            std::forward<_Args>(__args)...)),
            __depend);
       }
 
@@ -212,6 +213,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     void
     _M_start_thread(__shared_base_type);
 #endif
+
+  private:
+    // A call wrapper that does INVOKE(forwarded tuple elements...)
+    template<typename _Tuple>
+      struct _Invoker
+      {
+       _Tuple _M_t;
+
+       template<size_t _Index>
+         static __tuple_element_t<_Index, _Tuple>&&
+         _S_declval();
+
+       template<size_t... _Ind>
+         auto
+         _M_invoke(_Index_tuple<_Ind...>)
+         noexcept(noexcept(std::__invoke(_S_declval<_Ind>()...)))
+         -> decltype(std::__invoke(_S_declval<_Ind>()...))
+         { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }
+
+       using _Indices
+         = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
+
+       using result_type
+         = decltype(std::declval<_Invoker>()._M_invoke(_Indices()));
+
+       result_type
+       operator()()
+       noexcept(noexcept(std::declval<_Invoker>()._M_invoke(_Indices())))
+       { return _M_invoke(_Indices()); }
+
+      };
+
+    // Alias for _Invoker<tuple<DECAY_COPY(_Tp)...>>
+    template<typename... _Tp>
+      using __invoker_type
+       = _Invoker<decltype(std::make_tuple(std::declval<_Tp>()...))>;
+
+  public:
+    // Returns a call wrapper that does
+    // INVOKE(DECAY_COPY(__callable), DECAY_COPY(__args)).
+    template<typename _Callable, typename... _Args>
+      static __invoker_type<_Callable, _Args...>
+      __make_invoker(_Callable&& __callable, _Args&&... __args)
+      {
+       return { {
+           std::make_tuple(std::forward<_Callable>(__callable),
+                           std::forward<_Args>(__args)...)
+       } };
+      }
   };
 
   inline void