Missmiaom
4/2/2020 - 7:40 AM

future

future

future 对象必须由以下三种方式创建才被视为有效状态:

  • async
  • promise::get_future
  • packaged_task::get_future

使用默认构造函数将被视为非法状态。

std::future<int> fut = std::async (get_int);

// wait and get result
int res = fut.get();

packaged_task

std::packaged_task 包装任何可调用 (Callable) 目标(函数、 lambda 表达式、 bind 表达式或其他函数对象),使得能异步调用它。

其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中。

int f(int x, int y) { return std::pow(x,y); }
 
void task_lambda() {
    std::packaged_task<int(int,int)> task([](int a, int b) {
        return std::pow(a, b); 
    });
    std::future<int> result = task.get_future();
 
    task(2, 9);
 
    std::cout << "task_lambda:\t" << result.get() << '\n';
}
 
void task_bind() {
    std::packaged_task<int()> task(std::bind(f, 2, 11));
    std::future<int> result = task.get_future();
 
    task();
 
    std::cout << "task_bind:\t" << result.get() << '\n';
}
 
void task_thread() {
    std::packaged_task<int(int,int)> task(f);
    std::future<int> result = task.get_future();
 
    std::thread task_td(std::move(task), 2, 10);
    task_td.join();
 
    std::cout << "task_thread:\t" << result.get() << '\n';
}

promise

// promise::set_exception
#include <iostream>       // std::cin, std::cout, std::ios
#include <functional>     // std::ref
#include <thread>         // std::thread
#include <future>         // std::promise, std::future
#include <exception>      // std::exception, std::current_exception

void get_int (std::promise<int>& prom) {
  int x;
  std::cout << "Please, enter an integer value: ";
  std::cin.exceptions (std::ios::failbit);   // throw on failbit
  try {
    std::cin >> x;                           // sets failbit if input is not int
    prom.set_value(x);
  }
  catch (std::exception&) {
    prom.set_exception(std::current_exception());
  }
}

void print_int (std::future<int>& fut) {
  try {
    int x = fut.get();
    std::cout << "value: " << x << '\n';
  }
  catch (std::exception& e) {
    std::cout << "[exception caught: " << e.what() << "]\n";
  }
}

int main ()
{
  std::promise<int> prom;
  std::future<int> fut = prom.get_future();

  std::thread th1 (print_int, std::ref(fut));
  std::thread th2 (get_int, std::ref(prom));

  th1.join();
  th2.join();
  return 0;
}

async

policydescription
launch::asyncAsynchronous: Launches a new thread to call fn (as if a thread object is constructed with fn and args as arguments, and accessing the shared state of the returned future joins it).
launch::deferredDeferred: The call to fn is deferred until the shared state of the returned future is accessed (with wait or get). At that point, fn is called and the function is no longer considered deferred. When this call returns, the shared state of the returned future is made ready.
launch::async丨launch::deferredAutomatic: The function chooses the policy automatically (at some point). This depends on the system and library implementation, which generally optimizes for the current availability of concurrency in the system.
// async example
#include <iostream>       // std::cout
#include <future>         // std::async, std::future

// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
  std::cout << "Calculating. Please, wait...\n";
  for (int i=2; i<x; ++i) if (x%i==0) return false;
  return true;
}

int main ()
{
  // call is_prime(313222313) asynchronously:
  std::future<bool> fut = std::async (is_prime,313222313);

  std::cout << "Checking whether 313222313 is prime.\n";
  // ...

  bool ret = fut.get();      // waits for is_prime to return

  if (ret) std::cout << "It is prime!\n";
  else std::cout << "It is not prime.\n";

  return 0;
}