Skip to content

Commit

Permalink
Forward future used with .then() to continuation
Browse files Browse the repository at this point in the history
  • Loading branch information
K-ballo committed Oct 29, 2017
1 parent d96af68 commit b5a3c9c
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 51 deletions.
139 changes: 107 additions & 32 deletions hpx/lcos/future.hpp
Expand Up @@ -430,9 +430,9 @@ namespace hpx { namespace lcos { namespace detail

template <typename Executor, typename Future, typename F, typename ... Ts>
inline typename hpx::traits::future_then_executor_result<
Executor, Future, F, Ts...
Executor, typename std::decay<Future>::type, F, Ts...
>::type
then_execute_helper(Executor const&, F&&, Future const&, Ts&&...);
then_execute_helper(Executor const&, F &&, Future &&, Ts &&...);

///////////////////////////////////////////////////////////////////////////
template <typename Future>
Expand Down Expand Up @@ -587,8 +587,8 @@ namespace hpx { namespace lcos { namespace detail
// function.
// - valid() == false on original future object immediately after it
// returns.
template <typename F>
typename util::lazy_enable_if<
template <typename Future, typename F>
static typename util::lazy_enable_if<
!hpx::traits::is_launch_policy<
typename std::decay<F>::type>::value &&
!hpx::traits::is_threads_executor<
Expand All @@ -603,25 +603,26 @@ namespace hpx { namespace lcos { namespace detail
typename std::decay<F>::type>::value
, hpx::traits::future_then_result<Derived, F>
>::type
then(F && f, error_code& ec = throws) const
then(Future && fut, F && f, error_code& ec = throws)
{
return then(launch::all, std::forward<F>(f), ec);
return then(std::forward<Future>(fut), launch::all,
std::forward<F>(f), ec);
}

template <typename Policy, typename F>
typename util::lazy_enable_if<
template <typename Future, typename Policy, typename F>
static typename util::lazy_enable_if<
hpx::traits::is_launch_policy<
typename std::decay<Policy>::type
>::value,
hpx::traits::future_then_result<Derived, F>
>::type
then(Policy && policy, F && f, error_code& ec = throws) const
then(Future && fut, Policy && policy, F && f, error_code& ec = throws)
{
typedef
typename hpx::traits::future_then_result<Derived, F>::result_type
result_type;

if (!shared_state_)
if (!fut.shared_state_)
{
HPX_THROWS_IF(ec, no_state,
"future_base<R>::then",
Expand All @@ -638,21 +639,21 @@ namespace hpx { namespace lcos { namespace detail

shared_state_ptr p =
detail::make_continuation<continuation_result_type>(
*static_cast<Derived const*>(this),
std::forward<Policy>(policy), std::forward<F>(f));
std::forward<Future>(fut), std::forward<Policy>(policy),
std::forward<F>(f));
return hpx::traits::future_access<future<result_type> >::create(
std::move(p));
}

template <typename F>
typename hpx::traits::future_then_result<Derived, F>::type
then(threads::executor& sched, F && f, error_code& ec = throws) const
template <typename Future, typename F>
static typename hpx::traits::future_then_result<Derived, F>::type
then(Future && fut, threads::executor& sched, F && f, error_code& ec = throws)
{
typedef
typename hpx::traits::future_then_result<Derived, F>::result_type
result_type;

if (!shared_state_)
if (!fut.shared_state_)
{
HPX_THROWS_IF(ec, no_state,
"future_base<R>::then",
Expand All @@ -669,25 +670,26 @@ namespace hpx { namespace lcos { namespace detail

shared_state_ptr p =
detail::make_continuation<continuation_result_type>(
*static_cast<Derived const*>(this), sched, std::forward<F>(f));
std::forward<Future>(fut), sched,
std::forward<F>(f));
return hpx::traits::future_access<future<result_type> >::create(
std::move(p));
}

#if defined(HPX_HAVE_EXECUTOR_COMPATIBILITY)
template <typename Executor, typename F>
template <typename Future, typename Executor, typename F>
HPX_DEPRECATED(HPX_DEPRECATED_MSG)
typename util::lazy_enable_if<
static typename util::lazy_enable_if<
hpx::traits::is_executor<Executor>::value
, hpx::traits::future_then_result<Derived, F>
>::type
then(Executor& exec, F && f, error_code& ec = throws) const
then(Future && fut, Executor& exec, F && f, error_code& ec = throws)
{
typedef
typename hpx::traits::future_then_result<Derived, F>::result_type
result_type;

if (!shared_state_)
if (!fut.shared_state_)
{
HPX_THROWS_IF(ec, no_state,
"future_base<R>::then",
Expand All @@ -704,26 +706,26 @@ namespace hpx { namespace lcos { namespace detail

shared_state_ptr p =
detail::make_continuation_exec_v1<continuation_result_type>(
*static_cast<Derived const*>(this), exec,
std::forward<Future>(fut), exec,
std::forward<F>(f));
return hpx::traits::future_access<future<result_type> >::
create(std::move(p));
}
#endif

template <typename Executor, typename F>
typename util::lazy_enable_if<
template <typename Future, typename Executor, typename F>
static typename util::lazy_enable_if<
hpx::traits::is_one_way_executor<
typename std::decay<Executor>::type>::value ||
hpx::traits::is_two_way_executor<
typename std::decay<Executor>::type>::value
, hpx::traits::future_then_executor_result<Executor, Derived, F>
>::type
then(Executor && exec, F && f, error_code& ec = throws)
then(Future && fut, Executor && exec, F && f, error_code& ec = throws)
{
// simply forward this to executor
return detail::then_execute_helper(exec, std::forward<F>(f),
*static_cast<Derived const*>(this));
std::forward<Future>(fut));
}

// Effects: blocks until the shared state is ready.
Expand Down Expand Up @@ -1021,7 +1023,8 @@ namespace hpx { namespace lcos
then(F && f, error_code& ec = throws)
{
invalidate on_exit(*this);
return base_type::then(std::forward<F>(f), ec);
return base_type::then(std::move(*this),
std::forward<F>(f), ec);
}

template <typename Policy, typename F>
Expand All @@ -1034,7 +1037,7 @@ namespace hpx { namespace lcos
then(Policy && policy, F && f, error_code& ec = throws)
{
invalidate on_exit(*this);
return base_type::then(
return base_type::then(std::move(*this),
std::forward<Policy>(policy), std::forward<F>(f), ec);
}

Expand All @@ -1043,7 +1046,8 @@ namespace hpx { namespace lcos
then(threads::executor& sched, F && f, error_code& ec = throws)
{
invalidate on_exit(*this);
return base_type::then(sched, std::forward<F>(f), ec);
return base_type::then(std::move(*this),
sched, std::forward<F>(f), ec);
}

#if defined(HPX_HAVE_EXECUTOR_COMPATIBILITY)
Expand All @@ -1056,7 +1060,8 @@ namespace hpx { namespace lcos
then(Executor& exec, F && f, error_code& ec = throws)
{
invalidate on_exit(*this);
return base_type::then(exec, std::forward<F>(f), ec);
return base_type::then(std::move(*this),
exec, std::forward<F>(f), ec);
}
#endif

Expand All @@ -1071,7 +1076,8 @@ namespace hpx { namespace lcos
then(Executor && exec, F && f, error_code& ec = throws)
{
invalidate on_exit(*this);
return base_type::then(exec, std::forward<F>(f), ec);
return base_type::then(std::move(*this),
exec, std::forward<F>(f), ec);
}

using base_type::wait;
Expand Down Expand Up @@ -1339,7 +1345,76 @@ namespace hpx { namespace lcos
using base_type::has_value;
using base_type::has_exception;

using base_type::then;
template <typename F>
typename util::lazy_enable_if<
!hpx::traits::is_launch_policy<
typename std::decay<F>::type>::value &&
!hpx::traits::is_threads_executor<
typename std::decay<F>::type>::value &&
#if defined(HPX_HAVE_EXECUTOR_COMPATIBILITY)
!hpx::traits::is_executor<
typename std::decay<F>::type>::value &&
#endif
!hpx::traits::is_one_way_executor<
typename std::decay<F>::type>::value &&
!hpx::traits::is_two_way_executor<
typename std::decay<F>::type>::value
, hpx::traits::future_then_result<shared_future, F>
>::type
then(F && f, error_code& ec = throws) const
{
return base_type::then(*this,
std::forward<F>(f), ec);
}

template <typename Policy, typename F>
typename util::lazy_enable_if<
hpx::traits::is_launch_policy<
typename std::decay<Policy>::type
>::value,
hpx::traits::future_then_result<shared_future, F>
>::type
then(Policy && policy, F && f, error_code& ec = throws) const
{
return base_type::then(*this,
std::forward<Policy>(policy), std::forward<F>(f), ec);
}

template <typename F>
typename hpx::traits::future_then_result<shared_future, F>::type
then(threads::executor& sched, F && f, error_code& ec = throws) const
{
return base_type::then(*this,
sched, std::forward<F>(f), ec);
}

#if defined(HPX_HAVE_EXECUTOR_COMPATIBILITY)
template <typename Executor, typename F>
HPX_DEPRECATED(HPX_DEPRECATED_MSG)
typename util::lazy_enable_if<
hpx::traits::is_executor<Executor>::value
, hpx::traits::future_then_result<shared_future, F>
>::type
then(Executor& exec, F && f, error_code& ec = throws) const
{
return base_type::then(*this,
exec, std::forward<F>(f), ec);
}
#endif

template <typename Executor, typename F>
typename util::lazy_enable_if<
hpx::traits::is_one_way_executor<
typename std::decay<Executor>::type>::value ||
hpx::traits::is_two_way_executor<
typename std::decay<Executor>::type>::value
, hpx::traits::future_then_executor_result<Executor, shared_future, F>
>::type
then(Executor && exec, F && f, error_code& ec = throws) const
{
return base_type::then(*this,
exec, std::forward<F>(f), ec);
}

using base_type::wait;
using base_type::wait_for;
Expand Down
8 changes: 4 additions & 4 deletions hpx/lcos/local/packaged_continuation.hpp
Expand Up @@ -31,8 +31,8 @@
#include <exception>
#include <functional>
#include <mutex>
#include <utility>
#include <type_traits>
#include <utility>

///////////////////////////////////////////////////////////////////////////////
namespace hpx { namespace lcos { namespace detail
Expand Down Expand Up @@ -720,14 +720,14 @@ namespace hpx { namespace lcos { namespace detail

template <typename Executor, typename Future, typename F, typename ... Ts>
inline typename hpx::traits::future_then_executor_result<
Executor, Future, F, Ts...
Executor, typename std::decay<Future>::type, F, Ts...
>::type
then_execute_helper(Executor const& exec, F && f, Future const& predecessor,
then_execute_helper(Executor const& exec, F && f, Future && predecessor,
Ts &&... ts)
{
// simply forward this to executor
return parallel::execution::then_execute(exec, std::forward<F>(f),
predecessor, std::forward<Ts>(ts)...);
std::forward<Future>(predecessor), std::forward<Ts>(ts)...);
}
}}}

Expand Down
16 changes: 9 additions & 7 deletions hpx/parallel/executors/execution.hpp
Expand Up @@ -424,7 +424,7 @@ namespace hpx { namespace parallel { namespace execution
>::type
>
call_impl(hpx::traits::detail::wrap_int,
TwoWayExecutor && exec, F && f, Future& predecessor,
TwoWayExecutor && exec, F && f, Future && predecessor,
Ts &&... ts)
{
typedef typename hpx::util::detail::invoke_deferred_result<
Expand All @@ -449,28 +449,30 @@ namespace hpx { namespace parallel { namespace execution
typename ... Ts>
HPX_FORCEINLINE static auto
call_impl(int,
TwoWayExecutor && exec, F && f, Future& predecessor,
TwoWayExecutor && exec, F && f, Future && predecessor,
Ts &&... ts)
-> decltype(exec.then_execute(
std::forward<F>(f), predecessor, std::forward<Ts>(ts)...
std::forward<F>(f), std::forward<Future>(predecessor),
std::forward<Ts>(ts)...
))
{
return exec.then_execute(std::forward<F>(f),
predecessor, std::forward<Ts>(ts)...);
std::forward<Future>(predecessor), std::forward<Ts>(ts)...);
}

template <typename TwoWayExecutor, typename F, typename Future,
typename ... Ts>
HPX_FORCEINLINE static auto
call(TwoWayExecutor && exec, F && f, Future& predecessor,
call(TwoWayExecutor && exec, F && f, Future && predecessor,
Ts &&... ts)
-> decltype(call_impl(
0, std::forward<TwoWayExecutor>(exec), std::forward<F>(f),
predecessor, std::forward<Ts>(ts)...
std::forward<Future>(predecessor), std::forward<Ts>(ts)...
))
{
return call_impl(0, std::forward<TwoWayExecutor>(exec),
std::forward<F>(f), predecessor, std::forward<Ts>(ts)...);
std::forward<F>(f), std::forward<Future>(predecessor),
std::forward<Ts>(ts)...);
}
};

Expand Down

0 comments on commit b5a3c9c

Please sign in to comment.