Namespaces
Variants

Execution control library (since C++26)

From cppreference.net

La biblioteca de control de ejecución proporciona un marco para gestionar la ejecución asíncrona en recursos de ejecución genéricos.

La biblioteca tiene como objetivo proporcionar tipos de vocabulario para operaciones asíncronas y permitir la construcción de grafos de ejecución de tareas de manera simple y componible.

Contenidos

Definiciones de toda la biblioteca

  • Sender : Una descripción del trabajo asíncrono que se enviará para su ejecución. Produce un estado de operación (a continuación).
  • Los emisores asincrónicamente "envían" sus resultados a oyentes llamados "receptores" (a continuación).
  • Los emisores pueden componerse en grafos de tareas utilizando algoritmos genéricos.
  • Fábricas de emisores y adaptadores son algoritmos genéricos que capturan patrones asíncronos comunes en objetos que satisfacen el concepto sender .
  • Receiver : Un callback generalizado que consume o "recibe" los resultados asíncronos producidos por un sender.
  • Los receptores tienen tres "canales" diferentes a través de los cuales un emisor puede propagar resultados: éxito, fallo y cancelado, denominados "valor", "error" y "detenido".
  • Los receptores proporcionan un entorno de ejecución extensible: un conjunto de pares clave/valor que el consumidor puede utilizar para parametrizar la operación asíncrona.
  • Estado de Operación : Un objeto que contiene el estado necesario para la operación asíncrona.
  • Un emisor y un receptor están conectados cuando se pasan a la std::execution::connect function.
  • El resultado de conectar un emisor y un receptor es un estado de operación.
  • El trabajo no se encola para ejecución hasta que se llama a " start " en un estado de operación.
  • Una vez iniciado, el tiempo de vida del estado de operación no puede terminar antes de que la operación asíncrona se complete, y su dirección debe ser estable.
  • Scheduler : Un manejador ligero de un contexto de ejecución.
  • Un contexto de ejecución es una fuente de ejecución asíncrona como un grupo de hilos o un flujo de GPU.
  • Un planificador es una fábrica para un sender que completa su receiver desde un hilo de ejecución propiedad del contexto de ejecución.

Utilidades de biblioteca

Conceptos

Planificadores

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
especifica que un tipo es un scheduler
(concept)

Emisores

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
especifica que un tipo es un sender
(concept)
especifica un sender que puede crear operaciones asíncronas para un tipo de entorno asociado dado
(concept)
especifica un sender que puede conectarse con un tipo de receptor específico
(concept)

Receptores

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
especifica que un tipo es un receiver
(concept)
especifica que un tipo es un receiver para las firmas de finalización dadas
(concept)

Estados de operación

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
especifica que un tipo es un operation state
(concept)

Componentes de utilidad

Contextos de ejecución

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
recurso de ejecución que mantiene una cola de tareas MPSC segura para hilos y un bucle de eventos controlado manualmente
(clase)

Dominios de ejecución

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
tipo de etiqueta de dominio de ejecución predeterminado que despacha transformaciones desde una etiqueta de remitente
(clase)
transforma en un nuevo remitente bajo una etiqueta de dominio de ejecución dada
(plantilla de función)
transforma en un nuevo objeto consultable bajo una etiqueta de dominio de ejecución dada
(plantilla de función)
consume un remitente usando una etiqueta de consumidor de remitente dada con un conjunto de argumentos y devuelve su resultado bajo una etiqueta de dominio de ejecución dada
(plantilla de función)

Garantía de progreso hacia adelante

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
especifica una garantía de progreso hacia adelante de los agentes de ejecución creados por el recurso de ejecución asociado al planificador
(enumeración)

Entornos

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
construye un objeto consultable a partir de un objeto de consulta y un valor
(plantilla de clase)
agrega varios objetos consultables en un solo objeto consultable
(plantilla de clase)
devuelve el objeto consultable asociado para su argumento dado
(objeto de punto de personalización)

Consultas

Definido en el encabezado <execution>
consulta si un objeto de consulta debe ser reenviado a través de adaptadores consultables
(objeto de punto de personalización)
solicita a un objeto consultable su asignador asociado
(objeto de punto de personalización)
solicita a un objeto consultable su token de parada asociado
(objeto de punto de personalización)
solicita a un objeto consultable su etiqueta de dominio de ejecución asociada
(objeto de punto de personalización)
solicita a un objeto consultable su planificador asociado
(objeto de punto de personalización)
solicita a un objeto consultable un planificador que pueda utilizarse para delegar trabajo con el propósito de delegación de progreso hacia adelante
(objeto de punto de personalización)
obtiene el planificador de finalización asociado con una etiqueta de finalización a partir de los atributos de un emisor
(objeto de punto de personalización)
consulta a un planificador sobre su execution::forward_progress_guarantee
(objeto de punto de personalización)

Firmas de finalización

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
tipo que codifica un conjunto de firmas de finalización
(plantilla de clase)
obtiene las firmas de finalización de un emisor
(objeto de punto de personalización)
transforma un conjunto de firmas de finalización en otro
(plantilla de alias)
transforma las firmas de finalización de un emisor
(plantilla de alias)
obtiene el tipo de etiqueta de un emisor
(plantilla de alias)
obtiene el tipo de finalización de valor de un emisor
(plantilla de alias)
obtiene el tipo de finalización de error de un emisor
(plantilla de alias)
determina si el emisor admite finalización detenida
(plantilla de variable)

Utilidad de corrutinas

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
transforma una expresión en un objeto awaitable dentro de una corrutina particular
(objeto de punto de personalización)
cuando se usa como clase base de un tipo de promesa de corrutina, permite que los senders sean awaitables dentro de ese tipo de corrutina
(plantilla de clase)

Operaciones principales

Estado de operación

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
conecta un sender con un receiver
(objeto de punto de personalización)
inicia la operación asíncrona asociada con un objeto operation_state
(objeto de punto de personalización)

Funciones de finalización

Estas funciones son llamadas por los remitentes para anunciar la finalización del trabajo a sus receptores.

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
función de finalización de valor que indica finalización exitosa
(objeto de punto de personalización)
función de finalización de error que indica que ocurrió un error durante el cálculo o la programación
(objeto de punto de personalización)
función de finalización detenida que indica que una operación finalizó antes de poder alcanzar éxito o fallo
(objeto de punto de personalización)

Algoritmos del remitente

Fábricas de Sender

Una fábrica de emisores es una función que devuelve un emisor y cuyos parámetros tienen tipos para los cuales el concepto sender es false .

Los siguientes son fabricantes de remitentes:

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
Acepta un número variable de argumentos y retorna un sender que, cuando se conecta e inicia, completa sincrónicamente pasando los argumentos a la función de completado de valor del receptor
(objeto de punto de personalización)
Acepta un único argumento y retorna un sender que, cuando se conecta e inicia, completa sincrónicamente pasando el argumento a la función de completado de error del receptor
(objeto de punto de personalización)
crea un sender que completa inmediatamente llamando al set_stopped de su receptor
(objeto de punto de personalización)
crea un sender que consulta el entorno asociado de su receptor
(objeto de punto de personalización)
prepara un grafo de tareas para ejecución en un scheduler dado
(objeto de punto de personalización)

Adaptadores de emisor encadenables

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
clase base auxiliar de plantilla para definir un objeto de cierre de adaptador de emisor canalizable
(plantilla de clase)

Adaptadores de remitente

Un adaptador de emisor es una función que retorna un emisor cuyos parámetros incluyen al menos uno cuyo tipo satisface el concepto sender , y para el cual el emisor retornado es un emisor padre de los argumentos emisores de la función adaptadora.

Los siguientes son adaptadores de envío:

Definido en el encabezado <execution>
Definido en el espacio de nombres std::execution
adapta un emisor proporcionado en uno que iniciará una ejecución en el recurso de ejecución del planificador proporcionado
(objeto de punto de personalización)
adapta un sender proporcionado en uno que se completa en el recurso de ejecución del scheduler proporcionado
(objeto de punto de personalización)
adapta un sender proporcionado para transferir la ejecución al recurso de ejecución de un scheduler proporcionado en el cual el sender o la continuación se ejecuta, y luego transfiere la ejecución de vuelta al recurso original
(objeto de punto de personalización)
programa trabajo dependiente de la finalización de un sender proporcionado en el recurso de ejecución de un scheduler proporcionado
(objeto de punto de personalización)
encadena el grafo de tareas del sender de entrada con un nodo que representa la invocación de la función proporcionada con los valores enviados por el sender de entrada como argumentos
(objeto de punto de personalización)
encadena el gráfico de tareas del sender de entrada con un nodo que representa la invocación de la función proporcionada con el error enviado por el sender de entrada si ocurrió un error
(objeto de punto de personalización)
encadena el grafo de tareas del sender de entrada con un nodo que representa la invocación de la función proporcionada con el comportamiento de detención del sender de entrada si se envía una señal "stopped"
(objeto de punto de personalización)
devuelve un emisor que representa un nodo encadenado al emisor de entrada, que al iniciarse, invoca la función proporcionada con los valores enviados por el emisor de entrada como argumentos
(objeto de punto de personalización)
devuelve un sender que representa un nodo encadenado al sender de entrada, que invoca la función proporcionada con el error del sender de entrada, si ocurrió
(objeto de punto de personalización)
devuelve un sender que representa un nodo encadenado al sender de entrada, que invoca la función proporcionada con el token de parada del sender de entrada, si se envía la señal "stopped"
(objeto de punto de personalización)
crea un sender multi-shot que invoca la función con cada índice en la forma proporcionada junto con los valores enviados por el sender de entrada. El sender se completa una vez que todas las invocaciones han finalizado, o ha ocurrido un error
(objeto de punto de personalización)
si el sender proporcionado es un multi-shot sender, devuelve ese sender; de lo contrario, devuelve un multi-shot sender que envía valores equivalentes a los valores enviados por el sender proporcionado
(objeto de punto de personalización)
adapta múltiples emisores de entrada en un emisor que se completa una vez que todos los emisores de entrada han finalizado
(objeto de punto de personalización)
adapta múltiples emisores de entrada, cada uno posiblemente con múltiples firmas de finalización, en un emisor que se completa una vez que todos los emisores de entrada han finalizado
(objeto de punto de personalización)
devuelve un sender que envía una variant de tuplas de todos los conjuntos posibles de tipos enviados por el sender de entrada
(objeto de punto de personalización)
retorna un emisor que mapea el canal de valor a std:: optional < std:: decay_t < T >> y el canal de detención a std:: nullopt
(objeto de punto de personalización)
devuelve un emisor que mapea el canal detenido a un error
(objeto de punto de personalización)

Consumidores del remitente

Un consumidor de emisores es un algoritmo que toma uno o más emisores como parámetros y que no devuelve un emisor.

Definido en el encabezado <execution>
Definido en el espacio de nombres std::this_thread
bloquea el hilo actual hasta que el sender especificado se complete y devuelve su resultado asíncrono
(objeto de punto de personalización)
bloquea el hilo actual hasta que el sender especificado con posiblemente múltiples firmas de finalización se complete y devuelve su resultado asíncrono
(objeto de punto de personalización)

Ejemplo

Una versión de este ejemplo está disponible en godbolt.org , donde utiliza stdexec , una implementación de referencia experimental de std::execution .

#include <cstdio>
#include <execution>
#include <string>
#include <thread>
#include <utility>
using namespace std::literals;
int main()
{
    std::execution::run_loop loop;
    std::jthread worker([&](std::stop_token st)
    {
        std::stop_callback cb{st, [&]{ loop.finish(); }};
        loop.run();
    });
    std::execution::sender auto hello = std::execution::just("hello world"s);
    std::execution::sender auto print
        = std::move(hello)
        | std::execution::then([](std::string msg)
        {
            return std::puts(msg.c_str());
        });
    std::execution::scheduler auto io_thread = loop.get_scheduler();
    std::execution::sender auto work = std::execution::on(io_thread, std::move(print));
    auto [result] = std::this_thread::sync_wait(std::move(work)).value();
    return result;
}

Salida:

hello world

Véase también

(C++11)
ejecuta una función de forma asíncrona (potencialmente en un nuevo hilo) y devuelve un std::future que contendrá el resultado
(plantilla de función)