Итак, мы хотим реализовать конкретную схему:
- в одном потоке сдать пальто в чистку;
- в другом потоке пойти гулять с собакой, не дожидаясь окончания чистки.
Так выглядит синхронный вариант:
const CleaningReport report = CleanCoat(coat, money);
const bool is_dog_happy = WalkDog(dog);
А так — асинхронный:
#include <future>
// ...
future<CleaningReport> coat_future =
async([&coat, money] { return CleanCoat(coat, money); });
const bool is_dog_happy = WalkDog(dog); // любые действия, не связанные с пальто
const auto report = coat_future.get();
Обо всём по порядку:
- В библиотеке
<future>
объявлены функцияasync
и шаблонfuture
. async
принимает функцию, которую нужно запустить асинхронно. По возможности она запускается немедленно, а возвращается изasync
тот самый «талончик» — объектfuture<FunctionResult>
. Позже он позволит получить результат выполнения асихнронной функции типаFunctionResult
.- Гуляем с собакой. Если потоков достаточно, пальто уже чистится.
- Вызов метода
get
дляfuture<FunctionResult>
переводит текущий поток в режим ожидания окончания выполнения асинхронной функции. Как только она завершилась, изget
возвращается результат.
Функция async
умеет принимать не только функцию без параметров: после функции можно указать аргументы, с которыми она должна быть запущена. Но если указать их как есть, они скопируются:
future<CleaningReport> coat_future = async(CleanCoat, coat, money);
// за деньги не страшно (если это число), а вот тяжёлое пальто скопируется
Если аргумент нужно передать по ссылке, то надо обернуть его в ref
, а если по константной ссылке — в cref
:
#include <functional>
// ...
future<CleaningReport> coat_future = async(CleanCoat, ref(coat), money);
// деньги копируются, пальто передаётся по неконстантной ссылке