C++11多线程:future头文件

头文件可以通过特殊的provider进行数据的异步访问,实现线程间的通信。这些provider(无论是promise还是packaged_task对象,亦或是对async的调用)与future对象共享一个共享状态(share state)。provider共享状态就绪的时间点与future对象访问共享状态的点同步。
C++11多线程:future头文件_第1张图片

1. providers

1.1 promise

在这里插入图片描述

  • promise对象用来存储类型为T的数据,供future对象(可能在其他线程中)检索,它会提供一个同步点(共享状态就绪)。
  • 在构造时,promise对象与一个新的共享状态(share state)相关联,它可以在这个状态上存储类型为T的值,也可以存储从std::exception派生的异常。
  • 这个共享状态可以通过调用get_future与一个future对象相关联。函数调用后两个对象共享同一个共享状态。
  • 共享状态的生存周期持续到与之关联的最后一个对象释放它或者被销毁。

功能函数:
C++11多线程:future头文件_第2张图片
promise对象:异步的提供者(provider),在某个时候为共享状态(share state)设值。

future对象:异步的接收者,获取共享状态的值,必要时需要等待数据就绪。

示例:

// promise example
#include        // std::cout
#include      // std::ref
#include          // std::thread
#include          // std::promise, std::future

void print_int (std::future<int>& fut) {
  int x = fut.get();
  std::cout << "value: " << x << '\n';
}

int main ()
{
  std::promise<int> prom;                      // create promise

  std::future<int> fut = prom.get_future();    // engagement with future

  std::thread th1 (print_int, std::ref(fut));  // send future to new thread

  prom.set_value (10);                         // fulfill promise
                                               // (synchronizes with getting the future)
  th1.join();
  return 0;
}

输出:

value: 10

1)构造函数(constructor)

在这里插入图片描述
(1). 默认构造
构建一个promise对象,与一个空的共享对象相关联。
(2). 带分配器的构造
和(1)相同,但是用alloc为共享状态分配内存。
(3). 复制构造
禁用复制构造函数,promise对象不可被复制。
(4). 移动构造
对象获取x的共享状态,此后x等同于(1)。

示例:

// promise constructors
#include        // std::cout
#include      // std::ref
#include          // std::allocator, std::allocator_arg
#include          // std::thread
#include          // std::promise, std::future

void print_int (std::future<int>& fut) {
  int x = fut.get();
  std::cout << "value: " << x << '\n';
}

int main ()
{
  std::promise<int> foo;
  std::promise<int> bar = std::promise<int>(std::allocator_arg,std::allocator<int>());

  std::future<int> fut = bar.get_future();

  std::thread th (print_int, std::ref(fut));

  bar.set_value (20);

  th.join();
  return 0;
}

输出:

value: 20

2)std::promise::operator=

在这里插入图片描述
(1). 获取 rhs 的共享状态。原有的共享状态被丢弃(如同promise对象被销毁)。rhs失去共享状态,等同于默认构造,任何尝试访问其共享状态的操作都会被抛出future_error异常,异常类型为no_state
(2). promise对象不可复制。

示例:

// promise::operator=
#include        // std::cout
#include          // std::thread
#include          // std::promise, std::future

std::promise<int> prom;

void print_global_promise () {
  std::future<int> fut = prom.get_future();
  int x = fut.get();
  std::cout << "value: " << x << '\n';
}

int main ()
{
  std::thread th1 (print_global_promise);
  prom.set_value (10);
  th1.join();

  prom = std::promise<int>();    // reset, by move-assigning a new promise

  std::thread th2 (print_global_promise);
  prom.set_value (20);
  th2.join();

  return 0;
}

输出:

value: 10
value: 20

2)std::promise::get_future

在这里插入图片描述

  • 返回一个与该promise对象的共享状态相关联的future对象。该future可以获取promise对象在共享状态中设置的值或者异常。每个promise对象只匹配唯一的一个future对象。
  • 函数调用以后,promise需要通过设值使其共享状态就绪,否则它会自动存储future_error异常,为销毁做好准备,异常类型为 broken_promise

future_error:
C++11多线程:future头文件_第3张图片

3)std::promise::set_value

在这里插入图片描述
(1). 将val存入共享状态中,然后共享状态就绪。如果此时相关联的future对象正在等待数据(调用future.get),取消线程阻塞并返回val
(2). void特殊化成员函数,单纯令共享状态处于就绪,不设置任何值。

4)std::promise::set_value_at_thread_exit

在这里插入图片描述
(1). 将val存入共享状态中,线程退出时使其就绪。如果此时相关联的future对象正在等待数据(调用future.get),那么等待线程会一直阻塞,直到前面的线程退出,共享状态就绪,future获取值val。调用该函数后共享状态已被赋值,若在线程退出之前尝试修改共享状态就会抛出future_error异常,异常类型为 promise_already_satisfied
(2). void特殊化成员函数,单纯令共享状态处于就绪,不设置任何值。

5)std::promise::set_exception

在这里插入图片描述
将异常p存入共享状态,然后共享状态就绪。如果此时相关联的future对象正在等待数据(调用future.get),取消线程阻塞并返回异常p

示例:

// promise::set_exception
#include        // std::cin, std::cout, std::ios
#include      // std::ref
#include          // std::thread
#include          // std::promise, std::future
#include       // 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;
}

输出:

Please enter an integer value: boogey!
[exception caught: ios_base::failbit caught]

6)std::promise::set_exception_at_thread_exit

在这里插入图片描述
将异常p存入共享状态中,线程退出时使其就绪。如果此时相关联的future对象正在等待数据(调用future.get),那么等待线程会一直阻塞,直到前面的线程退出,共享状态就绪,future获取异常p。调用该函数后共享状态已被赋值,若在线程退出之前尝试修改共享状态就会抛出future_error异常,异常类型为 promise_already_satisfied

7)std::promise::swap & std::swap (promise)

在这里插入图片描述
promise对象与x交换共享状态。
在这里插入图片描述
等同于x.swap(y)

1.2 packaged_task

在这里插入图片描述
packaged_task用来包装一个可调用元素,供异步访问。它类似于std::function,不同的是它会自动向future对象传递数据。

packaged_task对象包含两个元素:
A. 存储任务(stored task)。一个可调用对象(例如函数指针,指向成员或者函数对象的指针),接受Args中的参数并返回Ret类型的值。
B. 共享状态(shared state)。存储A的返回结果(Ret类型),可通过future异步访问。

packaged_task对象的共享状态可以通过调用get_future与一个future对象相关联。函数调用后两个对象共享同一个共享状态。共享状态的生存周期持续到与之关联的最后一个对象释放它或者被销毁。

功能函数:
C++11多线程:future头文件_第4张图片
packaged_task对象:异步的提供者(provider),在某个时候为共享状态(share state)设值。

future对象:异步的接收者,获取共享状态的值,必要时需要等待数据就绪。

示例:

// packaged_task example
#include      // std::cout
#include        // std::packaged_task, std::future
#include        // std::chrono::seconds
#include        // std::thread, std::this_thread::sleep_for

// count down taking a second for each value:
int countdown (int from, int to) {
  for (int i=from; i!=to; --i) {
    std::cout << i << '\n';
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
  std::cout << "Lift off!\n";
  return from-to;
}

int main ()
{
  std::packaged_task<int(int,int)> tsk (countdown);   // set up packaged_task
  std::future<int> ret = tsk.get_future();            // get future

  std::thread th (std::move(tsk),10,0);   // spawn thread to count down from 10 to 0

  // ...

  int value = ret.get();                  // wait for the task to finish and get result

  std::cout << "The countdown lasted for " << value << " seconds.\n";

  th.join();

  return 0;
}

输出:

10
9
8
7
6
5
4
3
2
1
Lift off!
The countdown lasted for 10 seconds.

1)构造函数(constructor)

C++11多线程:future头文件_第5张图片
(1). 默认构造
构造一个packaged_task对象,没有共享状态(share state)和存储任务(stored task)。
(2). 初始化构造
构造一个packaged_task对象,开辟一个共享状态,存储任务初始化为fn
(3). 带分配器的初始化构造
和(2)相同,但是使用alloc来分配内存。
(4). 复制构造 [禁用]
禁用复制构造函数,packaged_task对象不可复制。
(5). 移动构造
构造的对象获得x的共享状态,x的存储任务也被转移,x变成状态(1)。

示例:

// packaged_task construction / assignment
#include      // std::cout
#include       // std::move
#include        // std::packaged_task, std::future
#include        // std::thread

int main ()
{
  std::packaged_task<int(int)> foo;                          // default-constructed
  std::packaged_task<int(int)> bar ([](int x){return x*2;}); // initialized

  foo = std::move(bar);                                      // move-assignment

  std::future<int> ret = foo.get_future();  // get future

  std::thread(std::move(foo),10).detach();  // spawn thread and call task

  // ...

  int value = ret.get();                    // wait for the task to finish and get result

  std::cout << "The double of 10 is " << value << ".\n";

  return 0;
}

输出:

The double of 10 is 20.

2)std::packaged_task::operator=

在这里插入图片描述
(1). ackaged_task对象获取 rhs 的共享状态和存储任务。在获取之前,对象先抛弃原有的共享状态(如同packaged_task对象被销毁)。此后 rhs 不再拥有共享状态,所有试图访问其共享状态的操作都会导致 future_error 异常报出,异常类型为 no_state
(2). ackaged_task对象不可复制。

3)std::packaged_task::valid

在这里插入图片描述
检查packaged_task当前是否有关联的共享状态。对于默认构造的packaged_task对象,函数返回false(除非被移动赋值或者被交换了)。

示例:

// packaged_task::valid
#include      // std::cout
#include       // std::move
#include        // std::packaged_task, std::future
#include        // std::thread

// function that launches an int(int) packaged_task in a new thread:
std::future<int> launcher (std::packaged_task<int(int)>& tsk, int arg) {
	if (tsk.valid()) {
      std::future<int> ret = tsk.get_future();
	  std::thread (std::move(tsk),arg).detach();
	  return ret;
	}
	else return std::future<int>();
}

int main ()
{
  std::packaged_task<int(int)> tsk ([](int x){return x*2;});

  std::future<int> fut = launcher (tsk,25);

  std::cout << "The double of 25 is " << fut.get() << ".\n";

  return 0;
}

输出:

The double of 25 is 50.

4)std::packaged_task::get_future

在这里插入图片描述
返回一个与该packaged_task对象的共享状态相关联的future对象。该future可以获取packaged_task对象在共享状态中设置的值或者异常。每个packaged_task对象只匹配唯一的一个future对象。函数调用以后,packaged_task需要通过调用其存储任务使其共享状态就绪,否则它会自动存储 future_error 异常,为销毁做好准备,异常类型为 broken_promise

示例:

// packaged_task::get_future
#include      // std::cout
#include       // std::move
#include        // std::packaged_task, std::future
#include        // std::thread

// a simple task:
int triple (int x) { return x*3; }

int main ()
{
  std::packaged_task<int(int)> tsk (triple); // package task

  std::future<int> fut = tsk.get_future();   // get future

  std::thread(std::move(tsk),33).detach();   // spawn thread and call task

  // ...

  int value = fut.get();                     // wait for the task to complete and get result

  std::cout << "The triple of 33 is " << value << ".\n";

  return 0;
}

输出:

The triple of 33 is 99.

5)std::packaged_task::operator()

在这里插入图片描述
调用存储任务,args为其传入参数。如果存储任务调用成功,任务返回值存入共享状态中;如果存储任务调用失败,抛出异常存入到共享状态中。这两种情况都会使存储状态就绪,阻塞线程(如果有)被唤醒。获取共享状态数据前,需要先获取future对象(get_future),然后通过future对象的get函数获取数据.

存储任务通常在packaged_task构造的时候确定,调用效果取决于该任务的类型:(没理解)

  • 如果存储任务是一个函数对象或者函数指针,它会调用相应的函数。
  • 如果存储任务是一个指向非静态成员函数的指针,传入的第一个参数作为调用对象(可以是对象、引用,或者指向他们的指针),剩下的参数作为调用对象的传入参数。
  • 如果存储任务是一个指向非静态数据成员的指针,此时只能传入一个参数(可能是一个对象、引用,或者一个指向他们的指针),构造函数会存储该成员的引用到共享状态中。

The stored task is generally specified on construction. The effects of calling it depend on its type:

  • If the stored task is a function pointer or a function object, it is called forwarding the arguments to the call.
  • If the stored task is a pointer to a non-static member function, it is called using the first argument as the object on which the member is called (this may either be an object, a reference, or a pointer to it), and the remaining arguments are forwarded as arguments for the member function.
  • If it is a pointer to a non-static data member, it should be called with a single argument, and the function stores in the shared state a reference to that member of its argument (the argument may either be an object, a reference, or a pointer to it).

6) std::packaged_task::make_ready_at_thread_exit

在这里插入图片描述
std::promise::set_value_at_thread_exit一个道理。

7)std::packaged_task::reset

在这里插入图片描述
新建一个共享状态替换packaged_task对象的共享状态,原有的共享状态被舍弃(如同packaged_task对象被销毁)。存储任务保持不变,此后存储任务可以被再次调用。系统内部等同于用std::packaged_task::operator=构建了一个新的packaged_task对象(存储任务不变)。

示例:

// packaged_task::reset
#include      // std::cout
#include       // std::move
#include        // std::packaged_task, std::future
#include        // std::thread

// a simple task:
int triple (int x) { return x*3; }

int main ()
{
  std::packaged_task<int(int)> tsk (triple); // package task

  std::future<int> fut = tsk.get_future();
  tsk(33);
  std::cout << "The triple of 33 is " << fut.get() << ".\n";

  // re-use same task object:
  tsk.reset();
  fut = tsk.get_future();
  std::thread(std::move(tsk),99).detach();
  std::cout << "Thre triple of 99 is " << fut.get() << ".\n";

  return 0;
}

输出:

The triple of 33 is 99.
The triple of 99 is 297.

8)std::packaged_task::swap & std::swap (packaged_task)

在这里插入图片描述
对象与 x 交换共享状态和存储任务。
在这里插入图片描述
等同于x.swap(y)

1.3 std::async

在这里插入图片描述
(1). 在某个时候调用 fn (以 args 作为参数),不等 fn 执行完成就可返回。返回结果为一个future对象,可以通过future::get获得 fn 的返回值。
(2). 该版本允许调用者自定义启动策略,版本(1)默认的自动选择,如同以 launch::async|launch::deferred 的启动策略运行版本(2)。

函数临时存储在共享状态中,要么是线程处理句柄使用的共享状态,要么是 fnargs(如同推迟函数deferred function)衰变副本中的共享状态,两种情况下共享状态都没有就绪。一旦 fn 运行结束,共享状态存入 fn 的返回值并就绪。(没理解)
The function temporarily stores in the shared state either the threading handler used or decay copies of fn and args (as a deferred function) without making it ready. Once the execution of fn is completed, the shared state contains the value returned by fn and is made ready.

启动策略:

  • launch::async
    异步:启动一个新的进程运行 fn(如同用 fn 新建了一个线程,args为参数,通过返回的future对象访问共享状态)。
  • launch::deferred
    推迟:推迟对 fn 的调用,直到返回的future对象的共享状态被申请访问(is accessed)(std::future::wait或者std::future::get被调用)。此时,fn 被调用,不再处于“推迟”状态。fn 返回后,future对象的共享状态就绪。
  • launch::async|launch::deferred
    自动:函数在某个时间点自适应选择上述两种启动策略。这取决于系统和库的实现,通常选取对当前系统并发可用性最为优化的模式。

函数返回:
返回一个future对象,当 fn 执行结束后,future对象的共享状态就绪。
launch::async 模式下,线程创建成功就返回future对象,即使该对象的共享状态从未被访问:在这种情况下,随着 fn 的返回,future对象同步销毁。因此,即使 fn 返回void,异步行为也不能忽略返回值。

示例:

// async example
#include        // std::cout
#include          // 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;
}

输出:

Checking whether 313222313 is prime.
Calculating. Please, wait...
It is prime!

2. futures

2.1 future

在这里插入图片描述
future对象可以从provider对象或程序中获取数据,如果在不同的线程中,则正确同步此访问,借此实现线程间的通信。

我们称一个与共享状态想关联的future对象为“有效的”(valid),这种对象可以通过以下方式获得:

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

只有“有效的”future对象才有作用,默认构造的future对象就不是“有效的”(除非被一个“有效的”future对象移动赋值)。

通过对一个“有效的”的future对象调用future::get来获取共享数据。如果此时provider的共享状态已就绪(通过向其中写入值或者异常),则返回共享数据;如果还未就绪,调用线程阻塞,直到provider的共享状态就绪。通过这种方法实现两个线程之间的同步。

共享状态的生存周期持续到与之关联的最后一个对象释放它或者被销毁。

功能函数:
C++11多线程:future头文件_第6张图片
示例:

// future example
#include        // std::cout
#include          // std::async, std::future
#include          // std::chrono::milliseconds

// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
  for (int i=2; i<x; ++i) if (x%i==0) return false;
  return true;
}

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

  // do something while waiting for function to set future:
  std::cout << "checking, please wait";
  std::chrono::milliseconds span (100);
  while (fut.wait_for(span)==std::future_status::timeout)
    std::cout << '.' << std::flush;

  bool x = fut.get();     // retrieve return value

  std::cout << "\n444444443 " << (x?"is":"is not") << " prime.\n";

  return 0;
}

输出(时间不尽相同):

checking, please wait........................
444444443 is prime.

1)构造函数(constructor)

在这里插入图片描述
(1). 默认构造
创建一个空的future对象:无共享状态,所以不是“有效的”,但是可以被另一个“有效的”future对象移动赋值。
(2). 复制构造 [禁用]
禁用复制构造函数,future对象不可复制。(可复制的future对象见shared_future)
(3). 移动构造
获取 x 的共享状态,x 失去共享状态,状态变成(1)。

示例:

// future::future
#include        // std::cout
#include          // std::async, std::future

int get_value() { return 10; }

int main ()
{
  std::future<int> foo;                            // default-constructed
  std::future<int> bar = std::async (get_value);   // move-constructed

  int x = bar.get();

  std::cout << "value: " << x << '\n';

  return 0;
}

输出:

value: 10

2)std::future::operator=

在这里插入图片描述
(1). 获取 rhs 的的共享状态。如果调用以前该对象是”有效的“,它会断开与之前共享状态的关联,如果之前的共享状态只与该对象关联,断开连接后之前的共享状态自行销毁。调用之后 rhs 失去共享状态,等同于默认构造的future对象,不再是“有效的”。
(2). future对象不可复制。

示例:

// future::operator=
#include        // std::cout
#include          // std::async, std::future

int get_value() { return 10; }

int main ()
{
  std::future<int> fut;           // default-constructed
  fut = std::async (get_value);   // move-assigned

  std::cout << "value: " << fut.get() << '\n';

  return 0;
}

输出:

value: 10

3)std::future::share

在这里插入图片描述
返回一个shared_future对象,它获得该future对象(*this)的共享状态,future对象失去共享状态变成默认构造状态,不再是“有效的”。

示例:

// future::share
#include        // std::cout
#include          // std::async, std::future, std::shared_future

int get_value() { return 10; }

int main ()
{
  std::future<int> fut = std::async (get_value);
  std::shared_future<int> shfut = fut.share();

  // shared futures can be accessed multiple times:
  std::cout << "value: " << shfut.get() << '\n';
  std::cout << "its double: " << shfut.get()*2 << '\n';

  return 0;
}

输出:

value: 10
its double: 20

4)std::future::get

在这里插入图片描述
在共享状态就绪的时候返回其存储的值或者异常。若共享状态此时还未就绪,函数会阻塞调用线程直到共享状态就绪。一旦就绪,函数会唤醒阻塞线程,并返回共享状态中的数据。此后future对象将不再是“有效的”:对于每个共享状态该函数最多调用一次。线程的同步分别发生在共享状态的就绪和函数返回两处。

版本(3)是void特殊化版本,函数不返回任何数据,但还是要等到共享状态就绪再释放它。

示例:

// future::get
#include        // std::cout, std::ios
#include          // std::async, std::future
#include       // std::exception

int get_int() {
  std::cin.exceptions (std::ios::failbit);   // throw on failbit set
  int x;
  std::cin >> x;                             // sets failbit if invalid
  return x;
}

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

  std::cout << "Please, enter an integer value: ";

  try {
    int x = fut.get();
    std::cout << "You entered: " << x << '\n';
  }
  catch (std::exception&) {
    std::cout << "[exception caught]";
  }

  return 0;
}

输出:

Please, enter an integer value: 101
You entered: 101

5)std::future::valid

在这里插入图片描述
检测当前future对象是否“有效的”(有关联的共享状态)。当future对象是默认构造(且未被移动赋值),或者已调用过一次future::get函数(且未被移动赋值),返回false。

示例:

// future::valid
#include        // std::cout
#include          // std::async, std::future
#include         // std::move

int get_value() { return 10; }

int main ()
{
  std::future<int> foo,bar;
  foo = std::async (get_value);
  bar = std::move(foo);

  if (foo.valid())
    std::cout << "foo's value: " << foo.get() << '\n';
  else
    std::cout << "foo is not valid\n";

  if (bar.valid())
    std::cout << "bar's value: " << bar.get() << '\n';
  else
    std::cout << "bar is not valid\n";

  return 0;
}

输出:

foo is not valid
bar's value: 10

6)std::future::wait(仅提供同步)

在这里插入图片描述
等待共享状态就绪。若共享状态此时还未就绪,函数会阻塞调用线程直到共享状态就绪。一旦就绪,函数会唤醒阻塞线程,然后直接返回,不获取共享状态中的数据。线程的同步分别发生在共享状态的就绪和函数返回两处。

示例:

// future::wait
#include        // std::cout
#include          // std::async, std::future
#include          // std::chrono::milliseconds

// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
  for (int i=2; i<x; ++i) if (x%i==0) return false;
  return true;
}

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

  std::cout << "checking...\n";
  fut.wait();

  std::cout << "\n194232491 ";
  if (fut.get())      // guaranteed to be ready (and not block) after wait returns
    std::cout << "is prime.\n";
  else
    std::cout << "is not prime.\n";

  return 0;
}

输出:

checking...
194232491 is prime.

7)std::future::wait_for

在这里插入图片描述
和std::future::wait基本相同,只是加了时间段(rel_time)限制。

  • 因共享状态就绪返回,同std::future::wait。
  • 因超时返回,无作为,不提供同步。

若未就绪的共享状态具有推迟功能(例如以 launch::deferred 模式调用async返回的future),函数不阻塞线程,而是直接返回 future_status::deferred

future_status
在这里插入图片描述
示例:

// future::wait_for
#include        // std::cout
#include          // std::async, std::future
#include          // std::chrono::milliseconds

// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
  for (int i=2; i<x; ++i) if (x%i==0) return false;
  return true;
}

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

  // do something while waiting for function to set future:
  std::cout << "checking, please wait";
  std::chrono::milliseconds span (100);
  while (fut.wait_for(span)==std::future_status::timeout)
    std::cout << '.';

  bool x = fut.get();

  std::cout << "\n700020007 " << (x?"is":"is not") << " prime.\n";

  return 0;
}

输出(时间不尽相同):

checking, please wait..........................................
700020007 is prime.

8)std::future::wait_until

在这里插入图片描述
和std::future::wait_for 基本相同,时间段(rel_time)换成了时间点(abs_time)。

2.2 shared_future

在这里插入图片描述
shared_future和future功能基本一样,shared_future相比future主要有以下几点区别:

  • 对象可以被复制。
  • 多个shared_future可以在共享状态的末端共享所有权(more than one shared_future can share ownership over their end of a shared state)。(没理解)
  • 共享状态就绪后可以被多次获取(future只能获取一次)。

功能函数:
C++11多线程:future头文件_第7张图片

参考

[1]. http://www.cplusplus.com/reference/future/

你可能感兴趣的:(C++11多线程:future头文件)