Execution control library (since C++26)
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
|
|
|
(C++26)
|
especifica que un tipo es un scheduler
(concept) |
Emisores
|
Definido en el encabezado
<execution>
|
|
|
Definido en el espacio de nombres
std::execution
|
|
|
(C++26)
|
especifica que un tipo es un sender
(concept) |
|
(C++26)
|
especifica un sender que puede crear operaciones asíncronas para un tipo de entorno asociado dado
(concept) |
|
(C++26)
|
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
|
|
|
(C++26)
|
especifica que un tipo es un receiver
(concept) |
|
(C++26)
|
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
|
|
|
(C++26)
|
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
|
|
|
(C++26)
|
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
|
|
|
(C++26)
|
tipo de etiqueta de dominio de ejecución predeterminado que despacha transformaciones desde una etiqueta de remitente
(clase) |
|
(C++26)
|
transforma en un nuevo remitente bajo una etiqueta de dominio de ejecución dada
(plantilla de función) |
|
(C++26)
|
transforma en un nuevo objeto consultable bajo una etiqueta de dominio de ejecución dada
(plantilla de función) |
|
(C++26)
|
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
|
|
|
(C++26)
|
construye un objeto consultable a partir de un objeto de consulta y un valor
(plantilla de clase) |
|
(C++26)
|
agrega varios objetos consultables en un solo objeto consultable
(plantilla de clase) |
|
(C++26)
|
devuelve el objeto consultable asociado para su argumento dado
(objeto de punto de personalización) |
Consultas
|
Definido en el encabezado
<execution>
|
|
|
(C++26)
|
consulta si un objeto de consulta debe ser reenviado a través de adaptadores consultables
(objeto de punto de personalización) |
|
(C++26)
|
solicita a un objeto consultable su asignador asociado
(objeto de punto de personalización) |
|
(C++26)
|
solicita a un objeto consultable su token de parada asociado
(objeto de punto de personalización) |
|
(C++26)
|
solicita a un objeto consultable su etiqueta de dominio de ejecución asociada
(objeto de punto de personalización) |
|
(C++26)
|
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
|
|
|
(C++26)
|
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) |
|
|
(C++26)
|
obtiene el tipo de etiqueta de un emisor
(plantilla de alias) |
|
(C++26)
|
obtiene el tipo de finalización de valor de un emisor
(plantilla de alias) |
|
(C++26)
|
obtiene el tipo de finalización de error de un emisor
(plantilla de alias) |
|
(C++26)
|
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
|
|
|
(C++26)
|
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
|
|
|
(C++26)
|
conecta un
sender
con un
receiver
(objeto de punto de personalización) |
|
(C++26)
|
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
|
|
|
(C++26)
|
función de finalización de valor que indica finalización exitosa
(objeto de punto de personalización) |
|
(C++26)
|
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) |
|
(C++26)
|
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
|
Esta sección está incompleta
Motivo: Actualización en progreso al estándar actual |
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
|
|
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
crea un sender que completa inmediatamente llamando al
set_stopped
de su receptor
(objeto de punto de personalización) |
|
(C++26)
|
crea un sender que consulta el entorno asociado de su receptor
(objeto de punto de personalización) |
|
(C++26)
|
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
|
|
|
(C++26)
|
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) |
|
(C++26)
|
adapta un sender proporcionado en uno que se completa en el recurso de ejecución del scheduler proporcionado
(objeto de punto de personalización) |
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
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) |
|
(C++26)
|
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
|
|
|
(C++26)
|
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) |