Namespaces
Variants

std::execution:: scheduler

From cppreference.net
Défini dans l'en-tête <execution>
template < class Sch >

concept scheduler =
std:: derived_from <
typename std:: remove_cvref_t < Sch > :: scheduler_concept ,
scheduler_t > &&
/*queryable*/ < Sch > &&
requires ( Sch && sch )
{
{
std :: execution :: schedule ( std:: forward < Sch > ( sch ) )
} - > std :: execution :: sender ;
{
auto (
std :: execution :: get_completion_scheduler <
std :: execution :: set_value_t > (
std :: execution :: get_env (
std :: execution :: schedule (
std:: forward < Sch > ( sch ) ) ) )
} - > std:: same_as < std:: remove_cvref_t < Sch >> ;
} &&
std:: equality_comparable < std:: remove_cvref_t < Sch >> &&
std:: copy_constructible < std:: remove_cvref_t < Sch >> ;

} ;
(1) (depuis C++26)
Type d'étiquette d'assistance
struct scheduler_t { } ;
(2) (depuis C++26)

Le concept scheduler est modélisé par des types qui sont des planificateurs , c'est-à-dire des gestionnaires légers de ressources d'exécution tels que des pools de threads qui fonctionnent avec la bibliothèque d'exécution C++.

Exigences sémantiques

Étant donné un planificateur de type Sch et un environnement d'exécution de type Env tels que sender_in < schedule_result_t < Sch > , Env > est satisfait, alors /*sender-in-of*/ < schedule_result_t < Sch > , Env > est modélisé.

Le constructeur de copie, le destructeur, la comparaison d'égalité ou les fonctions membres d'échange du planificateur doivent être non générateurs d'exceptions.

Toutes ces fonctions membres ainsi que la fonction schedule du type planificateur doivent être thread-safe.

Deux ordonnanceurs sont égaux uniquement s'ils représentent la même ressource d'exécution.

Pour un planificateur donné sch , l'expression get_completion_scheduler < set_value_t > ( get_env ( schedule ( sch ) ) ) est égale à sch .

Pour un planificateur donné sch , si l'expression get_domain ( sch ) est bien formée, alors l'expression get_domain ( get_env ( schedule ( sch ) ) ) est également bien formée et a le même type.

Le destructeur d'un planificateur ne doit pas bloquer en attendant l'achèvement des récepteurs connectés aux objets émetteurs retournés par schedule (la ressource sous-jacente peut fournir une API distincte pour attendre l'achèvement des objets fonction soumis)

Exemples

Enrobage simple pour std::execution::run_loop qui interroge constamment la file d'attente de run_loop sur un seul thread dédié. Démonstration utilisant l'implémentation de référence préliminaire : https://godbolt.org/z/146fY4Y91

#include <execution>
#include <iostream>
#include <thread>
class single_thread_context
{
    std::execution::run_loop loop_{};
    std::jthread thread_;
public:
    single_thread_context()
        : thread_([this] { loop_.run(); })
    {}
    single_thread_context(single_thread_context&&) = delete;
    ~single_thread_context()
    {
        loop_.finish();
    }
    std::execution::scheduler auto get_scheduler() noexcept
    {
        return loop_.get_scheduler();
    }
};
int main()
{
    single_thread_context ctx;
    std::execution::sender auto snd =
        std::execution::schedule(ctx.get_scheduler())
        | std::execution::then([]
            {
                std::cout << "Hello world! Have an int.\n";
                return 015;
            })
        | std::execution::then([](int arg) { return arg + 42; });
    auto [i] = std::this_thread::sync_wait(snd).value();
    std::cout << "Back in the main thread, result is " << i << '\n';
}

Sortie :

Hello world! Have an int.
Back in the main thread, result is 55

Voir aussi

prépare un graphe de tâches pour l'exécution sur un ordonnanceur donné
(objet de point de personnalisation)