Execution control library (since C++26)
La bibliothèque de contrôle d'exécution fournit un cadre pour gérer l'exécution asynchrone sur des ressources d'exécution génériques.
La bibliothèque vise à fournir des types de vocabulaire pour les opérations asynchrones et à permettre la construction de graphes d'exécution de tâches de manière simple et composable.
Table des matières |
Définitions générales de la bibliothèque
- Sender : Une description de travail asynchrone à envoyer pour exécution. Produit un état d'opération (ci-dessous).
-
- Les expéditeurs « envoient » de manière asynchrone leurs résultats aux écouteurs appelés « récepteurs » (ci-dessous).
- Les expéditeurs peuvent être composés en graphes de tâches en utilisant des algorithmes génériques.
- Les fabriques d'expéditeurs et les adaptateurs sont des algorithmes génériques qui capturent les modèles asynchrones courants dans les objets satisfaisant le concept sender .
- Receiver : Un rappel généralisé qui consomme ou « reçoit » les résultats asynchrones produits par un expéditeur.
-
- Les récepteurs disposent de trois « canaux » différents par lesquels un émetteur peut propager les résultats : succès, échec et annulé, dénommés respectivement « valeur », « erreur » et « arrêté ».
- Les récepteurs fournissent un environnement d'exécution extensible : un ensemble de paires clé/valeur que le consommateur peut utiliser pour paramétrer l'opération asynchrone.
- État de l'opération : Un objet qui contient l'état requis par l'opération asynchrone.
-
- Un émetteur et un récepteur sont connectés lorsqu'ils sont passés à la std::execution::connect fonction.
- Le résultat de la connexion d'un émetteur et d'un récepteur est un état d'opération.
-
Le travail n'est pas mis en file d'attente pour exécution avant que «
start» ne soit appelé sur un état d'opération. - Une fois démarré, la durée de vie de l'état d'opération ne peut pas se terminer avant que l'opération asynchrone ne soit complète, et son adresse doit être stable.
- Scheduler : Un gestionnaire léger d'un contexte d'exécution.
-
- Un contexte d'exécution est une source d'exécution asynchrone telle qu'un pool de threads ou un flux GPU.
- Un planificateur est une fabrique pour un expéditeur qui complète son récepteur à partir d'un thread d'exécution appartenant au contexte d'exécution.
Utilitaires de bibliothèque
Concepts
Planificateurs
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
spécifie qu'un type est un scheduler
(concept) |
Émetteurs
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
spécifie qu'un type est un sender
(concept) |
|
(C++26)
|
spécifie un sender qui peut créer des opérations asynchrones pour un type d'environnement associé donné
(concept) |
|
(C++26)
|
spécifie un sender qui peut se connecter avec un type de receiver spécifique
(concept) |
Récepteurs
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
spécifie qu'un type est un receiver
(concept) |
|
(C++26)
|
spécifie qu'un type est un receiver pour des signatures d'achèvement données
(concept) |
États d'opération
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
spécifie qu'un type est un état d'opération
(concept) |
Composants utilitaires
Contextes d'exécution
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
ressource d'exécution contenant une file d'attente de tâches
MPSC
thread-safe et une boucle d'événements à commande manuelle
(classe) |
Domaines d'exécution
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
type d'étiquette de domaine d'exécution par défaut qui distribue les transformations depuis une étiquette d'émetteur
(classe) |
|
(C++26)
|
transforme en un nouvel émetteur sous une étiquette de domaine d'exécution donnée
(modèle de fonction) |
|
(C++26)
|
transforme en un nouvel objet interrogeable sous une étiquette de domaine d'exécution donnée
(modèle de fonction) |
|
(C++26)
|
consomme un émetteur en utilisant une étiquette de consommateur d'émetteur donnée avec un ensemble d'arguments et retourne son résultat sous une étiquette de domaine d'exécution donnée
(modèle de fonction) |
Garantie de progression
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
spécifie une
garantie de progression forward
des agents d'exécution créés par la ressource d'exécution associée au planificateur
(énumération) |
|
Environnements
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
construit un objet interrogeable à partir d'un objet de requête et d'une valeur
(modèle de classe) |
|
(C++26)
|
agrège plusieurs objets interrogeables en un seul objet interrogeable
(modèle de classe) |
|
(C++26)
|
retourne l'objet interrogeable associé pour son argument donné
(objet de point de personnalisation) |
Requêtes
|
Défini dans l'en-tête
<execution>
|
|
|
(C++26)
|
demande à un objet de requête s'il doit être transmis via des adaptateurs interrogeables
(objet point de personnalisation) |
|
(C++26)
|
demande à un objet interrogeable son allocateur associé
(objet point de personnalisation) |
|
(C++26)
|
demande à un objet interrogeable son jeton d'arrêt associé
(objet point de personnalisation) |
|
(C++26)
|
demande à un objet interrogeable son étiquette de domaine d'exécution associée
(objet point de personnalisation) |
|
(C++26)
|
demande à un objet interrogeable son ordonnanceur associé
(objet point de personnalisation) |
|
demande à un objet interrogeable un ordonnanceur pouvant être utilisé pour déléguer du travail dans le but d'une délégation de progression
(objet point de personnalisation) |
|
|
obtient l'ordonnanceur de complétion associé à une étiquette de complétion depuis les attributs d'un émetteur
(objet point de personnalisation) |
|
|
demande à un ordonnanceur sa
execution::forward_progress_guarantee
(objet point de personnalisation) |
|
Signatures de complétion
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
type qui encode un ensemble de signatures de complétion
(modèle de classe) |
|
obtient les signatures de complétion d'un expéditeur
(objet de point de personnalisation) |
|
|
transforme un ensemble de signatures de complétion en un autre
(alias de modèle) |
|
|
transforme les signatures de complétion d'un expéditeur
(alias de modèle) |
|
|
(C++26)
|
obtient le type de tag d'un expéditeur
(alias de modèle) |
|
(C++26)
|
obtient le type de complétion de valeur d'un expéditeur
(alias de modèle) |
|
(C++26)
|
obtient le type de complétion d'erreur d'un expéditeur
(alias de modèle) |
|
(C++26)
|
détermine si l'expéditeur prend en charge la complétion d'arrêt
(variable de modèle) |
Utilitaire de coroutine
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
transforme une expression en objet awaitable dans une coroutine particulière
(objet de point de personnalisation) |
|
lorsqu'utilisé comme classe de base d'un type de promesse de coroutine, permet aux senders d'être awaitable dans ce type de coroutine
(modèle de classe) |
|
Opérations principales
État de fonctionnement
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
connecte un
sender
avec un
receiver
(point de personnalisation) |
|
(C++26)
|
démarre l'opération asynchrone associée à un objet
operation_state
(point de personnalisation) |
Fonctions d'achèvement
Ces fonctions sont appelées par les expéditeurs pour annoncer l'achèvement du travail à leurs destinataires.
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
fonction d'achèvement de valeur indiquant une terminaison réussie
(objet de point de personnalisation) |
|
(C++26)
|
fonction d'achèvement d'erreur indiquant qu'une erreur s'est produite pendant le calcul ou la planification
(objet de point de personnalisation) |
|
(C++26)
|
fonction d'achèvement d'arrêt indiquant qu'une opération s'est terminée avant de pouvoir atteindre le succès ou l'échec
(objet de point de personnalisation) |
Algorithmes de l'émetteur
|
Cette section est incomplète
Motif : Mise à jour WIP en cours vers la norme actuelle |
Fabriques d'expéditeurs
Une fabrique d'expéditeur est une fonction qui retourne un expéditeur et dont les paramètres ont des types pour lesquels le concept
sender
est
false
.
Les éléments suivants sont des fabriques d'expéditeur :
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
Accepte un nombre variable d'arguments et retourne un expéditeur qui, lorsqu'il est connecté et démarré, se termine de manière synchrone en passant les arguments à la fonction d'achèvement de valeur du récepteur
(objet de point de personnalisation) |
|
(C++26)
|
Accepte un seul argument et retourne un expéditeur qui, lorsqu'il est connecté et démarré, se termine de manière synchrone en passant l'argument à la fonction d'achèvement d'erreur du récepteur
(objet de point de personnalisation) |
|
(C++26)
|
crée un expéditeur qui se termine immédiatement en appelant la fonction
set_stopped
de son récepteur
(objet de point de personnalisation) |
|
(C++26)
|
crée un expéditeur qui interroge l'environnement associé à son récepteur
(objet de point de personnalisation) |
|
(C++26)
|
prépare un graphe de tâches pour l'exécution sur un ordonnanceur donné
(objet de point de personnalisation) |
Adaptateurs d'émetteurs canalizables
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
classe de base utilitaire pour définir un objet de fermeture d'adaptateur d'émetteur pouvant être utilisé avec l'opérateur pipe
(modèle de classe) |
|
Adaptateurs d'émetteur
Un adaptateur d'émetteur est une fonction retournant un émetteur dont les paramètres incluent au moins un dont le type satisfait le
sender
concept, et pour lequel l'émetteur retourné est un émetteur parent des arguments émetteurs de la fonction adaptateur.
Les éléments suivants sont des adaptateurs d'émetteur :
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::execution
|
|
|
(C++26)
|
adapte un émetteur fourni en un émetteur qui démarrera une exécution sur la ressource d'exécution du planificateur fourni
(objet de point de personnalisation) |
|
(C++26)
|
adapte un expéditeur fourni en un qui se termine sur la ressource d'exécution du planificateur fourni
(objet de point de personnalisation) |
|
(C++26)
|
adapte un émetteur fourni pour transférer l'exécution vers la ressource d'exécution d'un ordonnanceur fourni sur laquelle l'émetteur ou la continuation s'exécute, puis retransfère l'exécution vers la ressource d'origine
(objet de point de personnalisation) |
|
(C++26)
|
planifie le travail dépendant de l'achèvement d'un émetteur fourni sur la ressource d'exécution d'un planificateur fourni
(objet de point de personnalisation) |
|
(C++26)
|
chaîne le graphe de tâches de l'émetteur d'entrée avec un nœud représentant l'invocation de la fonction fournie avec les valeurs envoyées par l'émetteur d'entrée comme arguments
(objet de point de personnalisation) |
|
(C++26)
|
chaîne le graphe de tâches à partir de l'émetteur d'entrée avec un nœud représentant l'appel de la fonction fournie avec l'erreur envoyée par l'émetteur d'entrée si une erreur s'est produite
(objet de point de personnalisation) |
|
(C++26)
|
chaîne le graphe de tâches de l'émetteur d'entrée avec un nœud représentant l'appel de la fonction fournie avec le comportement d'arrêt de l'émetteur d'entrée si un signal "stopped" est envoyé
(objet de point de personnalisation) |
|
(C++26)
|
renvoie un expéditeur qui représente un nœud enchaîné à l'expéditeur d'entrée, qui, lorsqu'il est démarré, invoque la fonction fournie avec les valeurs envoyées par l'expéditeur d'entrée comme arguments
(point de personnalisation d'objet) |
|
(C++26)
|
retourne un expéditeur qui représente un nœud enchaîné à l'expéditeur d'entrée, qui invoque la fonction fournie avec l'erreur de l'expéditeur d'entrée, si elle s'est produite
(objet de point de personnalisation) |
|
(C++26)
|
retourne un expéditeur qui représente un nœud enchaîné à l'expéditeur d'entrée, qui invoque la fonction fournie avec le jeton d'arrêt de l'expéditeur d'entrée, si le signal "arrêté" est envoyé
(objet de point de personnalisation) |
|
crée un émetteur multi-tir qui invoque la fonction avec chaque index dans la forme fournie ainsi que les valeurs envoyées par l'émetteur d'entrée. L'émetteur se termine une fois que toutes les invocations sont terminées, ou qu'une erreur s'est produite
(objet de point de personnalisation) |
|
|
(C++26)
|
si l'émetteur fourni est un émetteur multi-tir, retourne cet émetteur, sinon, retourne un émetteur multi-tir qui émet des valeurs équivalentes aux valeurs émises par l'émetteur fourni
(objet de point de personnalisation) |
|
(C++26)
|
adapte plusieurs émetteurs d'entrée en un émetteur qui se termine une fois que tous les émetteurs d'entrée ont terminé
(objet de point de personnalisation) |
|
(C++26)
|
adapte plusieurs émetteurs d'entrée, chacun pouvant avoir plusieurs signatures d'achèvement, en un émetteur qui se termine une fois que tous les émetteurs d'entrée ont terminé
(objet de point de personnalisation) |
|
(C++26)
|
retourne un expéditeur qui envoie une variante de tuples de tous les ensembles possibles de types envoyés par l'expéditeur d'entrée
(objet de point de personnalisation) |
|
(C++26)
|
retourne un expéditeur qui mappe le canal de valeur vers
std::
optional
<
std::
decay_t
<
T
>>
et le canal arrêté vers
std::
nullopt
(objet de point de personnalisation) |
|
(C++26)
|
retourne un expéditeur qui mappe le canal arrêté vers une erreur
(point de personnalisation d'objet) |
Consommateurs de l'émetteur
Un consommateur émetteur est un algorithme qui prend un ou plusieurs émetteurs en paramètres et qui ne retourne pas d'émetteur.
|
Défini dans l'en-tête
<execution>
|
|
|
Défini dans l'espace de noms
std::this_thread
|
|
|
(C++26)
|
bloque le thread courant jusqu'à ce que l'émetteur spécifié se termine et retourne son résultat asynchrone
(objet de point de personnalisation) |
|
bloque le thread courant jusqu'à ce que l'émetteur spécifié avec potentiellement plusieurs signatures d'achèvement se termine et retourne son résultat asynchrone
(objet de point de personnalisation) |
|
Exemple
Une version de cet exemple est disponible sur godbolt.org , où elle utilise stdexec , une implémentation de référence expérimentale 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; }
Sortie :
hello world
Voir aussi
|
(C++11)
|
exécute une fonction de manière asynchrone (potentiellement dans un nouveau thread) et retourne une
std::future
qui contiendra le résultat
(modèle de fonction) |