๐ŸŽ“ A1Learner
๐Ÿ”
0 of 28 lessons completed

C++ Futures and Async

A future is a handle for a value that will be ready later. std::async starts work and returns a future for its result.

One async task and one future

Main prints its own line first and then waits on get for the answer. The answer line always follows because it waits for the future.

#include <future>
#include <iostream>

int addScores(int first, int second) {
  return first + second;
}

int main() {
  std::future<int> result = std::async(std::launch::async, addScores, 19, 23);
  std::cout << "Task started" << std::endl;
  int answer = result.get();
  std::cout << "Answer: " << answer << std::endl;
  return 0;
}

Two futures read in a fixed order

Two async calls run under two futures. Main calls get on the first future before the second one, so the printed order never changes.

#include <future>
#include <iostream>

int addScores(int first, int second) {
  return first + second;
}

int multiplyScores(int first, int second) {
  return first * second;
}

int main() {
  std::future<int> sum = std::async(std::launch::async, addScores, 10, 20);
  std::future<int> product = std::async(std::launch::async, multiplyScores, 6, 7);
  std::cout << "Sum: " << sum.get() << std::endl;
  std::cout << "Product: " << product.get() << std::endl;
  return 0;
}

A packaged task on the main thread

The packaged task wraps a function and its future is taken before the task runs. Main runs the task itself and then reads the result from the future.

#include <future>
#include <iostream>

int multiplyValues(int first, int second) {
  return first * second;
}

int main() {
  std::packaged_task<int(int, int)> task(multiplyValues);
  std::future<int> result = task.get_future();
  task(8, 5);
  std::cout << "Result: " << result.get() << std::endl;
  return 0;
}

Example

#include <future>
#include <iostream>

int subtotal(int price, int count) {
  return price * count;
}

int main() {
  std::future<int> pens = std::async(std::launch::async, subtotal, 20, 3);
  std::future<int> books = std::async(std::launch::async, subtotal, 15, 2);
  std::future<int> cards = std::async(std::launch::async, subtotal, 4, 5);
  int pensTotal = pens.get();
  int booksTotal = books.get();
  int cardsTotal = cards.get();
  int total = pensTotal + booksTotal + cardsTotal;
  std::cout << "Pens: " << pensTotal << std::endl;
  std::cout << "Books: " << booksTotal << std::endl;
  std::cout << "Cards: " << cardsTotal << std::endl;
  std::cout << "Total: " << total << std::endl;
  return 0;
}

Key points

  • std::async runs a function and hands back a std::future for its return value.
  • get waits for the value and then returns it.
  • get can be called only once on a future.
  • Results print in the order main calls get, and that order is fixed by the code.
  • std::packaged_task wraps a function so its result can be read from a future.

In this example, three async calls each compute one subtotal for the bill. Main reads the futures in code order with get, so the lines print in a fixed order. The subtotals are 60, 30, and 20, and the bill total is 110.

Note

The order results print in is the order of the get calls, not the order the work finishes.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What does calling get on a future do?