execution_base

The contents of this module can be included with the header hpx/modules/execution_base.hpp. These headers may be used by user-code but are not guaranteed stable (neither header location nor contents). You are using these at your own risk. If you wish to use non-public functionality from a module we strongly suggest only including the module header hpx/modules/execution_base.hpp, not the particular header in which the functionality you would like to use is defined. See Public API for a list of names that are part of the public HPX API.

namespace hpx
namespace execution_base
struct agent_base

Public Functions

virtual ~agent_base()
virtual std::string description() const = 0
virtual context_base const &context() const = 0
virtual void yield(char const *desc) = 0
virtual void yield_k(std::size_t k, char const *desc) = 0
virtual void suspend(char const *desc) = 0
virtual void resume(char const *desc) = 0
virtual void abort(char const *desc) = 0
virtual void sleep_for(hpx::chrono::steady_duration const &sleep_duration, char const *desc) = 0
virtual void sleep_until(hpx::chrono::steady_time_point const &sleep_time, char const *desc) = 0
namespace hpx
namespace execution_base
class agent_ref

Public Functions

constexpr agent_ref()
constexpr agent_ref(agent_base *impl)
constexpr agent_ref(agent_ref const&)
constexpr agent_ref &operator=(agent_ref const&)
constexpr agent_ref(agent_ref&&)
constexpr agent_ref &operator=(agent_ref&&)
constexpr operator bool() const
void reset(agent_base *impl = nullptr)
void yield(char const *desc = "hpx::execution_base::agent_ref::yield")
void yield_k(std::size_t k, char const *desc = "hpx::execution_base::agent_ref::yield_k")
void suspend(char const *desc = "hpx::execution_base::agent_ref::suspend")
void resume(char const *desc = "hpx::execution_base::agent_ref::resume")
void abort(char const *desc = "hpx::execution_base::agent_ref::abort")
template<typename Rep, typename Period>
void sleep_for(std::chrono::duration<Rep, Period> const &sleep_duration, char const *desc = "hpx::execution_base::agent_ref::sleep_for")
template<typename Clock, typename Duration>
void sleep_until(std::chrono::time_point<Clock, Duration> const &sleep_time, char const *desc = "hpx::execution_base::agent_ref::sleep_until")
agent_base &ref()

Private Functions

void sleep_for(hpx::chrono::steady_duration const &sleep_duration, char const *desc)
void sleep_until(hpx::chrono::steady_time_point const &sleep_time, char const *desc)

Private Members

agent_base *impl_

Friends

friend constexpr bool operator==(agent_ref const &lhs, agent_ref const &rhs)
friend constexpr bool operator!=(agent_ref const &lhs, agent_ref const &rhs)
std::ostream &operator<<(std::ostream&, agent_ref const&)
namespace hpx
namespace execution_base
struct context_base

Public Functions

virtual ~context_base()
virtual resource_base const &resource() const = 0
namespace hpx
namespace execution
namespace experimental

Functions

template<typename O>
void start(O &&o)

start is a customization point object. The expression hpx::execution::experimental::start(r) is equivalent to:

  • r.start(), if that expression is valid. If the function selected does not signal the receiver r’s done channel, the program is ill-formed (no diagnostic required).

  • Otherwise, `start(r), if that expression is valid, with overload resolution performed in a context that include the declaration void start();

  • Otherwise, the expression is ill-formed.

The customization is implemented in terms of hpx::functional::tag_dispatch.

Variables

hpx::execution::experimental::start_t start
template<typename O>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::execution::experimental::is_operation_state_v=is_operation_state<O>::value
template<typename O>
struct is_operation_state
#include <operation_state.hpp>

An operation_state is an object representing the asynchronous operation that has been returned from calling hpx::execution::experimental::connect with a sender and a receiver. The only operation on an operation_state is:

  • hpx::execution::experimental::start

hpx::execution::experimental::start can be called exactly once. Once it has been invoked, the caller needs to ensure that the receiver’s completion signaling operations strongly happen before the destructor of the state is called. The call to hpx::execution::experimental::start needs to happen strongly before the completion signaling operations.

struct start_t : public hpx::functional::tag_priority_noexcept<start_t>

Friends

template<typename OperationState>
friend constexpr auto tag_override_dispatch(start_t, OperationState &o)
namespace hpx
namespace execution
namespace experimental

Functions

template<typename R, typename ...As>
void set_value(R &&r, As&&... as)

set_value is a customization point object. The expression hpx::execution::set_value(r, as...) is equivalent to:

  • r.set_value(as...), if that expression is valid. If the function selected does not send the value(s) as... to the Receiver r’s value channel, the program is ill-formed (no diagnostic required).

  • Otherwise, `set_value(r, as…), if that expression is valid, with overload resolution performed in a context that include the declaration void set_value();

  • Otherwise, the expression is ill-formed.

The customization is implemented in terms of hpx::functional::tag_dispatch.

template<typename R>
void set_done(R &&r)

set_done is a customization point object. The expression hpx::execution::set_done(r) is equivalent to:

  • r.set_done(), if that expression is valid. If the function selected does not signal the Receiver r’s done channel, the program is ill-formed (no diagnostic required).

  • Otherwise, `set_done(r), if that expression is valid, with overload resolution performed in a context that include the declaration void set_done();

  • Otherwise, the expression is ill-formed.

The customization is implemented in terms of hpx::functional::tag_dispatch.

template<typename R, typename E>
void set_error(R &&r, E &&e)

set_error is a customization point object. The expression hpx::execution::set_error(r, e) is equivalent to:

  • r.set_done(e), if that expression is valid. If the function selected does not send the error e the Receiver r’s error channel, the program is ill-formed (no diagnostic required).

  • Otherwise, `set_error(r, e), if that expression is valid, with overload resolution performed in a context that include the declaration void set_error();

  • Otherwise, the expression is ill-formed.

The customization is implemented in terms of hpx::functional::tag_dispatch.

Variables

hpx::execution::experimental::set_value_t set_value
hpx::execution::experimental::set_error_t set_error
hpx::execution::experimental::set_done_t set_done
template<typename T, typename E = std::exception_ptr>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::execution::experimental::is_receiver_v = is_receiver<T, E>::value
template<typename T, typename... As>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::execution::experimental::is_receiver_of_v=is_receiver_of<T, As...>::value
template<typename T, typename... As>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::execution::experimental::is_nothrow_receiver_of_v=is_nothrow_receiver_of<T, As...>::value
template<typename T, typename E>
struct is_receiver
#include <receiver.hpp>

Receiving values from asynchronous computations is handled by the Receiver concept. A Receiver needs to be able to receive an error or be marked as being canceled. As such, the Receiver concept is defined by having the following two customization points defined, which form the completion-signal operations:

  • hpx::execution::experimental::set_done

  • hpx::execution::experimental::set_error

Those two functions denote the completion-signal operations. The Receiver contract is as follows:

  • None of a Receiver’s completion-signal operation shall be invoked before hpx::execution::experimental::start has been called on the operation state object that was returned by connecting a Receiver to a sender hpx::execution::experimental::connect.

  • Once hpx::execution::start has been called on the operation state object, exactly one of the Receiver’s completion-signal operation shall complete without an exception before the Receiver is destroyed

Once one of the Receiver’s completion-signal operation has been completed without throwing an exception, the Receiver contract has been satisfied. In other words: The asynchronous operation has been completed.

See

hpx::execution::experimental::is_receiver_of

template<typename T, typename ...As>
struct is_receiver_of
#include <receiver.hpp>

The receiver_of concept is a refinement of the Receiver concept by requiring one additional completion-signal operation:

  • hpx::execution::set_value

This completion-signal operation adds the following to the Receiver’s contract:

  • If hpx::execution::set_value exits with an exception, it is still valid to call hpx::execution::set_error or hpx::execution::set_done

See

hpx::execution::traits::is_receiver

struct set_done_t : public hpx::functional::tag_priority_noexcept<set_done_t>

Friends

template<typename R>
friend constexpr auto tag_override_dispatch(set_done_t, R &&r)
struct set_error_t : public hpx::functional::tag_priority_noexcept<set_error_t>

Friends

template<typename R, typename E>
friend constexpr auto tag_override_dispatch(set_error_t, R &&r, E &&e)
struct set_value_t : public hpx::functional::tag_priority<set_value_t>

Friends

template<typename R, typename ...Args>
friend constexpr auto tag_override_dispatch(set_value_t, R &&r, Args&&... args)
namespace hpx
namespace util

Functions

constexpr bool register_lock(void const*, util::register_lock_data* = nullptr)
constexpr bool unregister_lock(void const*)
constexpr void verify_no_locks()
constexpr void force_error_on_lock()
constexpr void enable_lock_detection()
constexpr void disable_lock_detection()
constexpr void trace_depth_lock_detection(std::size_t)
constexpr void ignore_lock(void const*)
constexpr void reset_ignored(void const*)
constexpr void ignore_all_locks()
constexpr void reset_ignored_all()
std::unique_ptr<held_locks_data> get_held_locks_data()
constexpr void set_held_locks_data(std::unique_ptr<held_locks_data>&&)
struct ignore_all_while_checking

Public Functions

ignore_all_while_checking()
template<typename Lock, typename Enable>
struct ignore_while_checking

Public Functions

ignore_while_checking(void const*)
namespace hpx
namespace execution_base
struct resource_base
#include <resource_base.hpp>

TODO: implement, this is currently just a dummy.

Public Functions

virtual ~resource_base()
namespace hpx
namespace execution
namespace experimental

Typedefs

template<typename S, typename R>
using connect_result_t = typename hpx::util::invoke_result<connect_t, S, R>::type

Functions

template<typename E, typename F>
void execute(E &&e, F &&f)

execute is a customization point object. For some subexpression e and f, let E be decltype((e)) and let F be decltype((F)). The expression execute(e, f) is ill-formed if F does not model invocable, or if E does not model either executor or sender. The result of the expression hpx::execution::experimental::execute(e, f) is then equivalent to:

  • e.execute(f), if that expression is valid. If the function selected does not execute the function object f on the executor e, the program is ill-formed with no diagnostic required.

  • Otherwise, execute(e, f), if that expression is valid, with overload resolution performed in a context that includes the declaration void execute(); and that does not include a declaration of hpx::execution::experimental::execute. If the function selected by overload resolution does not execute the function object f on the executor e, the program is ill-formed with no diagnostic required.

  • Otherwise, execution::submit(e, as-receiver<remove_cvref_t<F>, E>{forward<F>(f)}) if

    • F is not an instance of as-invocable<R,E’> for some type R where E and E’ name the same type ignoring cv and reference qualifiers, and

    • invocable<remove_cvref_t<F>&> && sender_to<E, as-receiver<remove_cvref_t<F>, E>> is true

    where as-receiver is some implementation-defined class template equivalent to:

    template<class F, class>
    struct as-receiver {
      F f_;
      void set_value() noexcept(is_nothrow_invocable_v<F&>) {
        invoke(f_);
      }
      template<class E>
      [[noreturn]] void set_error(E&&) noexcept {
        terminate();
      }
      void set_done() noexcept {}
    };
    

The customization is implemented in terms of hpx::functional::tag_dispatch.

template<typename S, typename R>
void connect(S &&s, R &&r)

connect is a customization point object. For some subexpression s and r, let S be the type such that decltype((s)) is S and let R be the type such that decltype((r)) is R. The result of the expression hpx::execution::experimental::connect(s, r) is then equivalent to:

  • s.connect(r), if that expression is valid and returns a type satisfying the operation_state (

    See

    hpx::execution::experimental::traits::is_operation_state) and if S satisfies the sender concept.

  • s.connect(r), if that expression is valid and returns a type satisfying the operation_state (

    See

    hpx::execution::experimental::traits::is_operation_state) and if S satisfies the sender concept. Overload resolution is performed in a context that include the declaration void connect();

  • Otherwise, as-operation{s, r}, if

    • r is not an instance of as-receiver<F, S’> for some type F where S and S’ name the same type ignoring cv and reference qualifiers, and

    • receiver_of<R> && executor-of-impl<remove_cvref_t

template<typename S, typename R>
auto submit(S &&s, R &&r)

The name submit denotes a customization point object.

For some subexpressions s and r, let S be decltype((s)) and let R be decltype((r)). The expression submit(s, r) is ill-formed if sender_to<S, R> is not true. Otherwise, it is expression-equivalent to:

* s.submit(r), if that expression is valid and S models sender. If the
  function selected does not submit the receiver object r via the
  sender s, the program is ill-formed with no diagnostic required.

* Otherwise, submit(s, r), if that expression is valid and S models
  sender, with overload resolution performed in a context that
  includes the declaration

      void submit();

  and that does not include a declaration of execution::submit. If
  the function selected by overload resolution does not submit the
  receiver object r via the sender s, the program is ill-formed with
  no diagnostic required.

* Otherwise, start((newsubmit-state<S, R>{s,r})->state_),
  where submit-state is an implementation-defined class template
  equivalent to

      template<class S, class R>
      struct submit-state {
        struct submit-receiver {
          submit-state * p_;
          template<class...As>
            requires receiver_of<R, As...>
          void set_value(As&&... as) && noexcept(is_nothrow_receiver_of_v<R, As...>) {
            set_value(std::move(p_->r_), (As&&) as...);
            delete p_;
          }
          template<class E>
            requires receiver<R, E>
          void set_error(E&& e) && noexcept {
            set_error(std::move(p_->r_), (E&&) e);
            delete p_;
          }
          void set_done() && noexcept {
            set_done(std::move(p_->r_));
            delete p_;
          }
        };
        remove_cvref_t<R> r_;
        connect_result_t<S, submit-receiver> state_;
        submit-state(S&& s, R&& r)
          : r_((R&&) r)
          , state_(connect((S&&) s, submit-receiver{this})) {}
      };

The customization is implemented in terms of hpx::functional::tag_dispatch.

template<typename Executor, typename F, typename = std::enable_if_t<hpx::is_invocable<std::decay_t<F>&>::value && !detail::has_member_execute<Executor, F>::value && !detail::is_as_invocable<F>::value>>
constexpr auto tag_fallback_dispatch(execute_t, Executor &&executor, F &&f)

Variables

template<typename Sender>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::execution::experimental::is_sender_v = is_sender<Sender>::value
hpx::execution::experimental::execute_t execute
hpx::execution::experimental::connect_t connect
hpx::execution::experimental::submit_t submit
template<typename Executor>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::execution::experimental::is_executor_v=is_executor<Executor>::value
template<typename Executor, typename F>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::execution::experimental::is_executor_of_v=is_executor_of<Executor, F>::value
hpx::execution::experimental::schedule_t schedule
template<typename Scheduler>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::execution::experimental::is_scheduler_v=is_scheduler<Scheduler>::value
struct connect_t : public hpx::functional::tag_priority<connect_t>

Friends

template<typename S, typename R, typename = std::enable_if_t<is_sender_v<S> && is_receiver_v<R>>>
friend constexpr auto tag_override_dispatch(connect_t, S &&s, R &&r)
template<typename S, typename R, typename = std::enable_if_t<!detail::has_member_connect<S, R>::value && is_receiver_of_v<R> && detail::is_executor_of_base_impl<std::decay_t<S>, detail::as_invocable<std::decay_t<R>, S>>::value>>
friend constexpr auto tag_fallback_dispatch(connect_t, S &&s, R &&r)
struct execute_t : public hpx::functional::tag_priority<execute_t>

Friends

template<typename Executor, typename F, typename = std::enable_if_t<hpx::is_invocable<std::decay_t<F>&>::value && detail::is_executor_base<Executor>::value>>
friend constexpr auto tag_override_dispatch(execute_t, Executor &&executor, F &&f)
struct invocable_archetype

Public Functions

void operator()()
template<typename Sender>
struct is_sender
#include <sender.hpp>

The name schedule denotes a customization point object. For some subexpression s, let S be decltype((s)). The expression schedule(s) is expression-equivalent to:

* s.schedule(), if that expression is valid and its type models
  sender.
* Otherwise, schedule(s), if that expression is valid and its type
  models sender with overload resolution performed in a context that
  includes the declaration

      void schedule();

  and that does not include a declaration of schedule.

* Otherwise, as-sender<remove_cvref_t<S>>{s} if S satisfies
  executor, where as-sender is an implementation-defined class
  template equivalent to

      template<class E>
      struct as-sender {
      private:
        E ex_;
      public:
        template<template<class...> class Tuple, template<class...> class Variant>
          using value_types = Variant<Tuple<>>;
        template<template<class...> class Variant>
          using error_types = Variant<std::exception_ptr>;
        static constexpr bool sends_done = true;

        explicit as-sender(E e) noexcept
          : ex_((E&&) e) {}
        template<class R>
          requires receiver_of<R>
        connect_result_t<E, R> connect(R&& r) && {
          return connect((E&&) ex_, (R&&) r);
        }
        template<class R>
          requires receiver_of<R>
        connect_result_t<const E &, R> connect(R&& r) const & {
          return connect(ex_, (R&&) r);
        }
      };

 * Otherwise, schedule(s) is ill-formed.

The customization is implemented in terms of hpx::functional::tag_dispatch. A sender is a type that is describing an asynchronous operation. The operation itself might not have started yet. In order to get the result of this asynchronous operation, a sender needs to be connected to a receiver with the corresponding value, error and done channels:

  • hpx::execution::experimental::connect

In addition, hpx::execution::experimental::::sender_traits needs to be specialized in some form.

A sender’s destructor shall not block pending completion of submitted operations.

template<typename Sender, typename Receiver>
struct is_sender_to
#include <sender.hpp>

See

is_sender

struct schedule_t : public hpx::functional::tag_priority<schedule_t>

Friends

template<typename S>
friend constexpr auto tag_override_dispatch(schedule_t, S &&s)
template<typename S, typename = std::enable_if_t<!detail::has_member_schedule<S>::value>>
friend constexpr auto tag_fallback_dispatch(schedule_t, S &&s)
template<typename Sender>
struct sender_traits
#include <sender.hpp>

sender_traits expose the different value and error types exposed by a sender. This can be either specialized directly for user defined sender types or embedded value_types, error_types and sends_done inside the sender type can be provided.

Subclassed by hpx::execution::experimental::sender_traits< Sender & >, hpx::execution::experimental::sender_traits< Sender && >, hpx::execution::experimental::sender_traits< Sender const >, hpx::execution::experimental::sender_traits< Sender volatile >

template<>
struct sender_traits<void>

Public Types

template<>
using __unspecialized = void
struct submit_t : public hpx::functional::tag_priority<submit_t>

Public Members

hpx::execution::experimental::submit_t::state{            start((new detail::submit_state<S, R>{                       std::forward<S>(s), std::forward<R>(r)})                      ->state)

Friends

template<typename S, typename R, typename = std::enable_if_t<is_sender_to<S, R>::value>>
friend constexpr auto tag_override_dispatch(submit_t, S &&s, R &&r)
template<typename S, typename R, typename = std::enable_if_t<!detail::has_member_submit<S, R>::value>>
friend constexpr auto tag_fallback_dispatch(submit_t, S &&s, R &&r)
namespace hpx
namespace execution_base
namespace this_thread

Functions

hpx::execution_base::agent_ref agent()
void yield(char const *desc = "hpx::execution_base::this_thread::yield")
void yield_k(std::size_t k, char const *desc = "hpx::execution_base::this_thread::yield_k")
void suspend(char const *desc = "hpx::execution_base::this_thread::suspend")
template<typename Rep, typename Period>
void sleep_for(std::chrono::duration<Rep, Period> const &sleep_duration, char const *desc = "hpx::execution_base::this_thread::sleep_for")
template<class Clock, class Duration>
void sleep_until(std::chrono::time_point<Clock, Duration> const &sleep_time, char const *desc = "hpx::execution_base::this_thread::sleep_for")
struct reset_agent

Public Functions

reset_agent(detail::agent_storage*, agent_base &impl)
reset_agent(agent_base &impl)
~reset_agent()

Public Members

detail::agent_storage *storage_
agent_base *old_
namespace util

Functions

template<typename Predicate>
void yield_while(Predicate &&predicate, const char *thread_name = nullptr, bool allow_timed_suspension = true)
namespace hpx
namespace traits

Typedefs

template<typename T>
using is_one_way_executor_t = typename is_one_way_executor<T>::type
template<typename T>
using is_never_blocking_one_way_executor_t = typename is_never_blocking_one_way_executor<T>::type
template<typename T>
using is_bulk_one_way_executor_t = typename is_bulk_one_way_executor<T>::type
template<typename T>
using is_two_way_executor_t = typename is_two_way_executor<T>::type
template<typename T>
using is_bulk_two_way_executor_t = typename is_bulk_two_way_executor<T>::type
template<typename T>
using is_executor_any_t = typename is_executor_any<T>::type

Variables

template<typename T>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::traits::is_one_way_executor_v=is_one_way_executor<T>::value
template<typename T>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::traits::is_never_blocking_one_way_executor_v=is_never_blocking_one_way_executor<T>::value
template<typename T>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::traits::is_bulk_one_way_executor_v=is_bulk_one_way_executor<T>::value
template<typename T>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::traits::is_two_way_executor_v=is_two_way_executor<T>::value
template<typename T>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::traits::is_bulk_two_way_executor_v=is_bulk_two_way_executor<T>::value
template<typename T>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::traits::is_executor_any_v=is_executor_any<T>::value
template<typename Executor>
struct extract_executor_parameters<Executor, typename hpx::util::always_void<typename Executor::executor_parameters_type>::type>

Public Types

template<>
using type = typename Executor::executor_parameters_type
template<typename Parameters>
struct extract_has_variable_chunk_size<Parameters, typename hpx::util::always_void<typename Parameters::has_variable_chunk_size>::type>

Public Types

template<>
using type = typename Parameters::has_variable_chunk_size
namespace hpx
namespace parallel
namespace execution

Typedefs

template<typename T>
using is_executor_parameters_t = typename is_executor_parameters<T>::type

Variables

template<typename T>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::parallel::execution::is_executor_parameters_v=is_executor_parameters<T>::value
template<typename Executor, typename Enable = void>
struct extract_executor_parameters

Public Types

template<>
using type = sequential_executor_parameters
template<typename Executor>
struct extract_executor_parameters<Executor, typename hpx::util::always_void<typename Executor::executor_parameters_type>::type>

Public Types

template<>
using type = typename Executor::executor_parameters_type
template<typename Parameters, typename Enable = void>
struct extract_has_variable_chunk_size

Public Types

template<>
using type = std::false_type
template<typename Parameters>
struct extract_has_variable_chunk_size<Parameters, typename hpx::util::always_void<typename Parameters::has_variable_chunk_size>::type>

Public Types

template<>
using type = typename Parameters::has_variable_chunk_size
namespace traits

Typedefs

template<typename T>
using is_executor_parameters_t = typename is_executor_parameters<T>::type

Variables

template<typename T>HPX_INLINE_CONSTEXPR_VARIABLE bool hpx::traits::is_executor_parameters_v=is_executor_parameters<T>::value