diff --git a/include/__functional_base b/include/__functional_base index 22ac94719..518c9b7af 100644 --- a/include/__functional_base +++ b/include/__functional_base @@ -440,7 +440,7 @@ __invoke(_R (*__f)(_Param...), _Args&& ...__args) template inline _LIBCPP_INLINE_VISIBILITY -typename result_of<_F(_T...)>::type +typename __invoke_of<_F, _T...>::type __invoke(_F&& __f, _T&& ...__t) { return _STD::forward<_F>(__f)(_STD::forward<_T>(__t)...); @@ -476,7 +476,7 @@ public: // invoke template _LIBCPP_INLINE_VISIBILITY - typename __invoke_return::type + typename __invoke_of::type operator() (_ArgTypes&&... __args) const { return __invoke(get(), _STD::forward<_ArgTypes>(__args)...); diff --git a/include/future b/include/future index c60d3accf..471e1f2e6 100644 --- a/include/future +++ b/include/future @@ -858,6 +858,115 @@ __deferred_assoc_state::__execute() #endif // _LIBCPP_NO_EXCEPTIONS } +template +class __async_assoc_state + : public __assoc_state<_R> +{ + typedef __assoc_state<_R> base; + + _F __func_; + + virtual void __on_zero_shared(); +public: +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + explicit __async_assoc_state(_F&& __f); +#endif + + virtual void __execute(); +}; + +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +inline _LIBCPP_INLINE_VISIBILITY +__async_assoc_state<_R, _F>::__async_assoc_state(_F&& __f) + : __func_(_STD::forward<_F>(__f)) +{ +} + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +void +__async_assoc_state<_R, _F>::__execute() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + this->set_value(__func_()); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + this->set_exception(current_exception()); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template +void +__async_assoc_state<_R, _F>::__on_zero_shared() +{ + this->wait(); + base::__on_zero_shared(); +} + +template +class __async_assoc_state + : public __assoc_sub_state +{ + typedef __assoc_sub_state base; + + _F __func_; + + virtual void __on_zero_shared(); +public: +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + explicit __async_assoc_state(_F&& __f); +#endif + + virtual void __execute(); +}; + +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +inline _LIBCPP_INLINE_VISIBILITY +__async_assoc_state::__async_assoc_state(_F&& __f) + : __func_(_STD::forward<_F>(__f)) +{ +} + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +void +__async_assoc_state::__execute() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + __func_(); + this->set_value(); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + this->set_exception(current_exception()); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template +void +__async_assoc_state::__on_zero_shared() +{ + this->wait(); + base::__on_zero_shared(); +} + template class promise; template class shared_future; template class atomic_future; @@ -874,6 +983,14 @@ __make_deferred_assoc_state(_F&& __f); __make_deferred_assoc_state(_F __f); #endif +template +future<_R> +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +__make_async_assoc_state(_F&& __f); +#else +__make_async_assoc_state(_F __f); +#endif + template class _LIBCPP_VISIBLE future { @@ -885,11 +1002,16 @@ class _LIBCPP_VISIBLE future template friend class shared_future; template friend class atomic_future; - template #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + template friend future<_R1> __make_deferred_assoc_state(_F&& __f); + template + friend future<_R1> __make_async_assoc_state(_F&& __f); #else + template friend future<_R1> __make_deferred_assoc_state(_F __f); + template + friend future<_R1> __make_async_assoc_state(_F __f); #endif public: @@ -983,11 +1105,16 @@ class _LIBCPP_VISIBLE future<_R&> template friend class shared_future; template friend class atomic_future; - template #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + template friend future<_R1> __make_deferred_assoc_state(_F&& __f); + template + friend future<_R1> __make_async_assoc_state(_F&& __f); #else + template friend future<_R1> __make_deferred_assoc_state(_F __f); + template + friend future<_R1> __make_async_assoc_state(_F __f); #endif public: @@ -1076,11 +1203,16 @@ class _LIBCPP_VISIBLE future template friend class shared_future; template friend class atomic_future; - template #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + template friend future<_R1> __make_deferred_assoc_state(_F&& __f); + template + friend future<_R1> __make_async_assoc_state(_F&& __f); #else + template friend future<_R1> __make_deferred_assoc_state(_F __f); + template + friend future<_R1> __make_async_assoc_state(_F __f); #endif public: @@ -2034,32 +2166,68 @@ __make_deferred_assoc_state(_F __f) return future<_R>(__h.get()); } +template +future<_R> +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +__make_async_assoc_state(_F&& __f) +#else +__make_async_assoc_state(_F __f) +#endif +{ + unique_ptr<__async_assoc_state<_R, _F>, __release_shared_count> + __h(new __async_assoc_state<_R, _F>(_STD::forward<_F>(__f))); + _STD::thread(&__async_assoc_state<_R, _F>::__execute, __h.get()).detach(); + return future<_R>(__h.get()); +} + template -future::type> +class __async_func +{ + tuple<_F, _Args...> __f_; + +public: + typedef typename __invoke_of<_F, _Args...>::type _R; + + _LIBCPP_INLINE_VISIBILITY + explicit __async_func(_F&& __f, _Args&&... __args) + : __f_(_STD::move(__f), _STD::move(__args)...) {} + + _LIBCPP_INLINE_VISIBILITY + __async_func(__async_func&& __f) : __f_(_STD::move(__f.__f_)) {} + + _R operator()() + { + typedef typename __make_tuple_indices<1+sizeof...(_Args), 1>::type _Index; + return __execute(_Index()); + } +private: + template + _R + __execute(__tuple_indices<_Indices...>) + { + return __invoke(_STD::move(_STD::get<0>(__f_)), _STD::move(_STD::get<_Indices>(__f_))...); + } +}; + +template +future::type, typename decay<_Args>::type...>::type> async(launch __policy, _F&& __f, _Args&&... __args) { - typedef typename result_of<_F(_Args...)>::type _R; + typedef __async_func::type, typename decay<_Args>::type...> _BF; + typedef typename _BF::_R _R; future<_R> __r; if (__policy & launch::async) - { - packaged_task<_R()> __pk(bind(_STD::forward<_F>(__f), - _STD::forward<_Args>(__args)...)); - __r = __pk.get_future(); - thread(_STD::move(__pk)).detach(); - } + __r = _STD::__make_async_assoc_state<_R>(_BF(__decay_copy(_STD::forward<_F>(__f)), + __decay_copy(_STD::forward<_Args>(__args))...)); else if (__policy & launch::deferred) - __r = _STD::__make_deferred_assoc_state<_R>(bind(_STD::forward<_F>(__f), - _STD::forward<_Args>(__args)...)); + __r = _STD::__make_deferred_assoc_state<_R>(_BF(__decay_copy(_STD::forward<_F>(__f)), + __decay_copy(_STD::forward<_Args>(__args))...)); return __r; } template inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - !is_same::type, launch>::value, - future::type> ->::type +future::type, typename decay<_Args>::type...>::type> async(_F&& __f, _Args&&... __args) { return _STD::async(launch::any, _STD::forward<_F>(__f), diff --git a/include/mutex b/include/mutex index fcfe4b71d..69192a82f 100644 --- a/include/mutex +++ b/include/mutex @@ -485,7 +485,7 @@ private: _LIBCPP_INLINE_VISIBILITY void __execute(__tuple_indices<_Indices...>) { - _STD::move(_STD::get<0>(__f_))(_STD::move(_STD::get<_Indices>(__f_))...); + __invoke(_STD::move(_STD::get<0>(__f_)), _STD::move(_STD::get<_Indices>(__f_))...); } }; diff --git a/include/thread b/include/thread index ca16d2138..a04572f6b 100644 --- a/include/thread +++ b/include/thread @@ -325,7 +325,7 @@ inline _LIBCPP_INLINE_VISIBILITY void __threaad_execute(tuple<_F, _Args...>& __t, __tuple_indices<_Indices...>) { - _STD::move(_STD::get<0>(__t))(_STD::move(_STD::get<_Indices>(__t))...); + __invoke(_STD::move(_STD::get<0>(__t)), _STD::move(_STD::get<_Indices>(__t))...); } template diff --git a/include/type_traits b/include/type_traits index bb93fc36f..e4e96fe11 100644 --- a/include/type_traits +++ b/include/type_traits @@ -2772,7 +2772,132 @@ template struct _LIBCPP_VISIBLE is_trivial is_trivially_default_constructible<_Tp>::value> #endif {}; - + +#ifndef _LIBCPP_HAS_NO_VARIADICS + +// __invokable + +template +struct __invokable_imp + : false_type +{ +}; + +// __invokable member function pointer + +template +auto +__invokable_mfp_test(_A0&& __a0, _F __f, _Args&& ...__args) + -> decltype((_STD::forward<_A0>(__a0).*__f)(_STD::forward<_Args>(__args)...)); + +template +auto +__invokable_mfp_test(_A0&& __a0, _F __f, _Args&& ...__args) + -> decltype(((*_STD::forward<_A0>(__a0)).*__f)(_STD::forward<_Args>(__args)...)); + +template +auto +__invokable_mfp_test(__any, _F __f, _Args&& ...__args) + -> __nat; + +template +struct __invokable_imp<2, _F, _A0, _Args...> +{ + typedef decltype( + __invokable_mfp_test(_STD::declval<_A0>(), _STD::declval<_F>(), + _STD::declval<_Args>()...) + ) type; + static const bool value = !is_same::value; +}; + +// __invokable member object pointer + +template +auto +__invokable_mop_test(_A0&& __a0, _F __f) + -> decltype(_STD::forward<_A0>(__a0).*__f); + +template +auto +__invokable_mop_test(_A0&& __a0, _F __f) + -> decltype((*_STD::forward<_A0>(__a0)).*__f); + +template +auto +__invokable_mop_test(__any, _F __f) + -> __nat; + +template +struct __invokable_imp<1, _F, _A0> +{ + typedef decltype( + __invokable_mop_test(_STD::declval<_A0>(), _STD::declval<_F>()) + ) type; + static const bool value = !is_same::value; +}; + +// __invokable other + +template +auto +__invokable_other_test(_F&& __f, _Args&& ...__args) + -> decltype(_STD::forward<_F>(__f)(_STD::forward<_Args>(__args)...)); + +template +auto +__invokable_other_test(__any, _Args&& ...__args) + -> __nat; + +template +struct __invokable_imp<0, _F, _Args...> +{ + typedef decltype( + __invokable_other_test(_STD::declval<_F>(), _STD::declval<_Args>()...) + ) type; + static const bool value = !is_same::value; +}; + +// __invokable_classify + +template +struct __invokable_classify +{ + typedef typename remove_reference<_F>::type _FR; + static const unsigned value = is_member_function_pointer<_FR>::value ? + 2 : + is_member_object_pointer<_FR>::value ? + 1 : + 0; +}; + +template +struct __invokable + : public integral_constant::value, _F, _Args...>::value> +{ +}; + +// __invoke_of + +template +struct __invoke_of_imp // false +{ +}; + +template +struct __invoke_of_imp +{ + typedef typename __invokable_imp<__invokable_classify<_F>::value, _F, _Args...>::type type; +}; + +template +struct __invoke_of + : public __invoke_of_imp<__invokable<_F, _Args...>::value, _F, _Args...> +{ +}; + +#endif // _LIBCPP_HAS_NO_VARIADICS + template inline _LIBCPP_INLINE_VISIBILITY void