Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/execution"

From cppreference.com
< cpp
m (+std::)
m (Library-wide definitions: extended definitions are copied from Suggestions Page.)
Line 12: Line 12:
 
==Library-wide definitions==
 
==Library-wide definitions==
  
* '''Sender''' - Contains data and/or work to be sent for execution.
+
* '''Sender''': A description of asynchronous work to be sent for execution. Produces an operation state (below).
:* Senders can be chained to build execution pipes (translated into a tasks graph).
+
:* Senders asynchronously “send” their results to listeners called “receivers” (below).
:* Different types of senders can be produced by senders factories/adaptors.
+
:* Senders can be composed into '''task graphs''' using generic algorithms.
* '''Receiver/Sender Consumer''' - Closure of execution pipe, consume sender(s) and returns an Operation State.
+
:* '''Sender factories and adaptors''' are generic algorithms that capture common async patterns in objects satisfying the sender concept.
:* Receiver contains environment, which holds data on the execution context
+
* '''Receiver''': A generalized callback that consumes or “receives” the asynchronous results produced by a sender.
:* By default (if not provided) the environment is the default env.
+
:* Receivers have three different “channels” through which a sender may propagate results: success, failure, and canceled, so-named “value”, “error”, and “stopped”.
* '''Operation State''' - Object which holds: data + work + execution context. Executed by calling “start”
+
:* Receivers provide an extensible execution environment: a set of key/value pairs that the consumer can use to parameterize the asynchronous operation.
* '''Scheduler''' - Execution context on which operation can run (CPU, thread pool, GPU threads, Event loop, etc.)
+
* '''Operation State''': An object that contains the state needed by the asynchronous operation.
 +
:* A sender and receiver are connected when they are passed to the {{lc|std::execution::connect}} customization point.
 +
:* The result of connecting a sender and a receiver is an operation state.
 +
:* Work is not enqueued for execution until “{{tt|start}}” is called on an operation state.
 +
:* Once started, the operation state’s lifetime cannot end before the async operation is complete, and its address must be stable.
 +
* '''Scheduler''': A lightweight handle to an execution context.
 +
:* An execution context is a source of asynchronous execution such as a thread pool or a GPU stream.
 +
:* A scheduler is a factory for a sender that completes its receiver from a thread of execution owned by the execution context.
  
 
==Library utilities==
 
==Library utilities==

Revision as of 22:05, 11 February 2024

The Execution library provides a framework for managing asynchronous execution on generic execution resources, targeting the standard C++ library.

The library aims to provide vocabulary types for async operations and to allow the construction of task execution graphs in a simple, composable way.

Contents

Library-wide definitions

  • Sender: A description of asynchronous work to be sent for execution. Produces an operation state (below).
  • Senders asynchronously “send” their results to listeners called “receivers” (below).
  • Senders can be composed into task graphs using generic algorithms.
  • Sender factories and adaptors are generic algorithms that capture common async patterns in objects satisfying the sender concept.
  • Receiver: A generalized callback that consumes or “receives” the asynchronous results produced by a sender.
  • Receivers have three different “channels” through which a sender may propagate results: success, failure, and canceled, so-named “value”, “error”, and “stopped”.
  • Receivers provide an extensible execution environment: a set of key/value pairs that the consumer can use to parameterize the asynchronous operation.
  • Operation State: An object that contains the state needed by the asynchronous operation.
  • A sender and receiver are connected when they are passed to the std::execution::connect customization point.
  • The result of connecting a sender and a receiver is an operation state.
  • Work is not enqueued for execution until “start” is called on an operation state.
  • Once started, the operation state’s lifetime cannot end before the async operation is complete, and its address must be stable.
  • Scheduler: A lightweight handle to an execution context.
  • An execution context is a source of asynchronous execution such as a thread pool or a GPU stream.
  • A scheduler is a factory for a sender that completes its receiver from a thread of execution owned by the execution context.

Library utilities

Senders

Sender factories

A sender factory takes a non-sender (function/data) and returns a sender.

A sender with no completion schedulers is an “open-ended” operation, that can be used in the pipe. All the following senders are created without a completion scheduler.

Template:cpp/execution/dsc read
Defined in header <execution>
Defined in namespace std::execution
prepares a task graph for execution on a given scheduler
(customization point object)[edit]
Accepts a variadic number of arguments and returns a sender that, when connected and started, completes synchronously by passing the arguments to the receiver's value completion function
(customization point object)[edit]
Accepts a single argument and returns a sender that, when connected and started, completes synchronously by passing the argument to the receiver's error completion function
(customization point object)[edit]
creates a sender that completes immediately by calling its receiver's set_stopped
(customization point object)[edit]

Sender adaptors

A sender adaptor takes a sender and returns a sender.

The returned sender represents the task graph described by the input sender, with an additional node containing the functionality added by the adaptor.

Adaptors for single-shot and multi-shot senders
Defined in header <execution>
Defined in namespace std::execution
Returns a sender describes transition from the execution context of the input sender to the execution context of the target scheduler
(function template) [edit]
chains the task graph by the input sender with a node represents invoking the provided function with the values sent by the input sender as arguments
(customization point object)[edit]
chains the task graph by the input sender with a node representing invoking the provided function with the error sent by the input sender if an error occurred
(customization point object)[edit]
chains the task graph by the input sender with a node representing invoking the provided function with the stopped behavior by the input sender if a "stopped" signal is sent
(customization point object)[edit]
returns a sender which represents a node chained to the input sender, which when started, invokes the provided function with the values sent by the input sender as arguments
(customization point object)[edit]
returns a sender which represents a node chained to the input sender, which invokes the provided function with the error from the input sender, if occurred
(customization point object)[edit]
returns a sender which represents a node chained to the input sender, which invokes the provided function with the stop token from the input sender, if the "stopped" signal is sent
(customization point object)[edit]
start the provided sender on an execution agent belonging to the execution resource associated with the provided scheduler
(customization point object)[edit]
returns a sender which sends a variant of tuples of all the possible sets of types sent by the input sender
(customization point object)[edit]
returns a sender that maps the value channel to std::optional<std::decay_t<T>> and the stopped channel to std::nullopt
(customization point object)[edit]
returns a sender that maps the stopped channel to an error
(customization point object)[edit]
Eagerly starts a sender, returning a sender that will deliver the results to a receiver to which it is connected and started, if any. When the result sender is not connected to a receiver, or if the resulting operation state is not started, the results are ignored. If such a sender is destroyed before the underlying operation completes, the operation continues running detached.
(function template) [edit]
Adaptors for multi-shot senders
Defined in header <execution>
Defined in namespace std::execution
creates a multi-shot sender that invokes the function with every index in the provided shape along with the values sent by the input sender. The sender completes once all invocations have completed, or an error has occurred
(customization point object)[edit]
if the provided sender is a multi-shot sender, returns that sender, otherwise, returns a multi-shot sender which sends values equivalent to the values sent by the provided sender
(customization point object)[edit]
completes once all of the input senders have completed
(customization point object)[edit]

Sender consumers

A sender consumer is an algorithm that takes one or more senders as parameters and connects them. It does not return a sender.

Defined in header <execution>
Defined in namespace std::execution
Completes when the provided sender completes, or calls std::terminate if the sender sends an error.
(function template) [edit]
Functions managing the current thread
Defined in header <thread>
Defined in namespace std::this_thread
blocks current thread until the specified sender completes and returns its async result
(customization point object)[edit]

Eager execution

Allows a fire-and-forget eager one-way submission of an invocable to a scheduler.

Defined in header <execution>
Defined in namespace std::execution
Submits the provided function for execution on the provided scheduler.
(function template) [edit]

Example

Uses stdexec (available on godbolt), which is an experimental reference implementation for std::execution.

#include <iostream>
#include <stdexec/execution.hpp>
#include <thread>
 
stdexec::run_loop loop;
std::thread worker([]{ loop.run(); });
 
int main()
{
    using namespace std::literals;
 
    auto hello = stdexec::just("hello work"s);
    auto work = hello | stdexec::then([](auto msg)
    {
        std::cout << msg << '\n';
        return 0;
    });
 
    const auto [result] =
        stdexec::sync_wait(stdexec::on(loop.get_scheduler(), std::move(work))).value();
    loop.finish();
    worker.join();
    return result;
}

Output:

hello work

See also