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 ...
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.
# include <bits/c++0x_warning.h>
#else
-#include <functional>
#include <mutex>
#include <thread>
#include <condition_variable>
#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>
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));
}
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>
{
__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)
}
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);
}
#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)
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);
}
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