130 votes

Futurs et promesses

Je m'embrouille avec la différence entre un futur et une promesse.

Il est évident qu'ils ont des méthodes différentes, mais quel est le cas d'utilisation réel ?

Est-ce que c'est.. :

  • lorsque je gère une tâche asynchrone, j'utilise future pour obtenir la valeur "dans le futur".
  • lorsque je suis une tâche asynchrone, j'utilise une promesse comme type de retour pour permettre à l'utilisateur d'obtenir un futur à partir de ma promesse.

159voto

ronag Points 13051

Future et Promise sont les deux faces distinctes d'une opération asynchrone.

std::promise est utilisé par le "producteur/écrivain" de l'opération asynchrone.

std::future est utilisé par le "consommateur/lecteur" de l'opération asynchrone.

La raison pour laquelle il est séparé en deux "interfaces" distinctes est la suivante cacher la fonctionnalité "écrire/régler" du "consommateur/lecteur".

auto promise = std::promise<std::string>();

auto producer = std::thread([&]
{
    promise.set_value("Hello World");
});

auto future = promise.get_future();

auto consumer = std::thread([&]
{
    std::cout << future.get();
});

producer.join();
consumer.join();

Une façon (incomplète) d'implémenter std::async en utilisant std::promise pourrait être :

template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
    typedef decltype(func()) result_type;

    auto promise = std::promise<result_type>();
    auto future  = promise.get_future();

    std::thread(std::bind([=](std::promise<result_type>& promise)
    {
        try
        {
            promise.set_value(func()); // Note: Will not work with std::promise<void>. Needs some meta-template programming which is out of scope for this question.
        }
        catch(...)
        {
            promise.set_exception(std::current_exception());
        }
    }, std::move(promise))).detach();

    return std::move(future);
}

Utilisation de std::packaged_task qui est une aide (c'est-à-dire qu'il fait essentiellement ce que nous faisions ci-dessus) autour de std::promise vous pourriez faire ce qui suit, qui est plus complet et peut-être plus rapide :

template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
    auto task   = std::packaged_task<decltype(func())()>(std::forward<F>(func));
    auto future = task.get_future();

    std::thread(std::move(task)).detach();

    return std::move(future);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X