From 1c51095fa3672573b906aadcd1acfcdcf913ba24 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Mon, 10 May 2021 11:59:12 +0200 Subject: [PATCH] Add execution::keep_future to pass the future instead of its value to continuations when futures are used as senders keep_future passes the future instead of the value to help manage future lifetimes. Especially shared_future | on | ... is not possible without this helper if the wrapped value in the future is noncopyable (since shared_future::get returns a const& and on cannot store a const&, nor does it need to keep the operation state alive long enough). --- libs/parallelism/execution/CMakeLists.txt | 1 + .../hpx/execution/algorithms/keep_future.hpp | 159 ++++++++++++ .../executors/tests/unit/p0443_executor.cpp | 239 ++++++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 libs/parallelism/execution/include/hpx/execution/algorithms/keep_future.hpp diff --git a/libs/parallelism/execution/CMakeLists.txt b/libs/parallelism/execution/CMakeLists.txt index b8f65c5712cf..a898c25ff0eb 100644 --- a/libs/parallelism/execution/CMakeLists.txt +++ b/libs/parallelism/execution/CMakeLists.txt @@ -15,6 +15,7 @@ set(execution_headers hpx/execution/algorithms/ensure_started.hpp hpx/execution/algorithms/just.hpp hpx/execution/algorithms/just_on.hpp + hpx/execution/algorithms/keep_future.hpp hpx/execution/algorithms/let_error.hpp hpx/execution/algorithms/let_value.hpp hpx/execution/algorithms/on.hpp diff --git a/libs/parallelism/execution/include/hpx/execution/algorithms/keep_future.hpp b/libs/parallelism/execution/include/hpx/execution/algorithms/keep_future.hpp new file mode 100644 index 000000000000..069c2da7d234 --- /dev/null +++ b/libs/parallelism/execution/include/hpx/execution/algorithms/keep_future.hpp @@ -0,0 +1,159 @@ +// Copyright (c) 2021 ETH Zurich +// +// SPDX-License-Identifier: BSL-1.0 +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace hpx { namespace execution { namespace experimental { + namespace detail { + template + struct operation_state + { + std::decay_t receiver; + std::decay_t future; + + void start() & noexcept + { + try + { + auto state = hpx::traits::detail::get_shared_state(future); + + if (!state) + { + HPX_THROW_EXCEPTION(no_state, "operation_state::start", + "the future has no valid shared state asdasd"); + } + + state->set_on_completed( + [this, receiver = std::move(receiver)]() mutable { + hpx::execution::experimental::set_value( + std::move(receiver), std::move(future)); + }); + } + catch (...) + { + hpx::execution::experimental::set_error( + std::move(receiver), std::current_exception()); + } + } + }; + template + struct keep_future_sender_base + { + std::decay_t future; + + template