飞道的博客

C++11中std::shared_future的使用

318人阅读  评论(0)

C++11中的std::shared_future是个模板类。std::future类似,std::shared_future提供了一种访问异步操作结果的机制;不同于std::future,std::shared_future允许多个线程等待同一个共享状态;不同于std::future仅支持移动操作,std::shared_future既支持移动操作也支持拷贝操作,而且多个shared_future对象可以引用相同的共享状态。std::shared_future还允许一旦共享状态就绪就可以多次检索共享状态下的值(A shared_future object behaves like a future object, except that it can be copied, and that more than one shared_future can share ownership over their end of a shared state. They also allow the value in the shared state to be retrieved multiple times once ready)。

std::shared_future对象可以通过std::future对象隐式转换,也可以通过显示调用std::future::share显示转换,在这两种情况下,原std::future对象都将变得无效。

共享状态(shared state)的生存期至少要持续到与之关联的最后一个对象被销毁为止。与std::future不同,通过shared_future::get检索的值不会释放共享对象的所有权。

std::future介绍参考:https://blog.csdn.net/fengbingchun/article/details/104115489

当你需要具有std::future的多个有效拷贝时会用到std::shared_future;或者多个使用者使用std::future时也会用到std::shared_future。

Consider std::future, std::shared_future to be like std::unique_ptr, std::shared_ptr.

模板类std::shared_future成员函数包括:

1. 构造函数:(1).不带参数的默认构造函数,此对象没有共享状态,因此它是无效的,但是它可以被赋予一个有效值;(2).拷贝构造:与const shared_future& x具有相同的共享状态,并与之共享所有权;(3).支持移动构造。

2. 析构函数:销毁shared_future对象,它是异常安全的。如果对象有效(即它可以访问共享状态),则将其与对象接触关联;如果它是与共享状态关联的唯一对象,则共享对象本身也将被销毁。

3. get函数:(1).当共享状态就绪时,返回存储在共享状态中的值的引用(或抛出异常)。(2).如果共享状态尚未就绪(即provider提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪。(3).当共享状态就绪后,则该函数将解除阻塞并返回(或抛出),但与future::get不同,不会释放其共享状态,允许其它shared_future对象也访问存储的值。(4).std::shared_future<void>::get()不返回任何值,但仍等待共享状态就绪才返回或抛出。

4. operator=:(1).拷贝赋值:该对象与const shared_future& rhs关联到相同的共享状态,并与之共享所有权;(2).移动赋值:该对象获取shared_future&& rhs的共享状态,rhs不再有效。

5. valid函数:检查共享状态的有效性,返回当前的shared_future对象是否与共享状态关联。

6. wait函数:(1).等待共享状态就绪。(2).如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪。(3).当共享状态就绪后,则该函数将解除阻塞并void返回。

7. wait_for函数:(1).等待共享状态在指定的时间内(time span)准备就绪。(2). 如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪或已达到设置的时间。(3).此函数的返回值类型为枚举类future_status。此枚举类有三种label:ready:共享状态已就绪;timeout:在指定的时间内未就绪;deferred:共享状态包含了一个延迟函数(deferred function)。(4).如果共享状态包含了一个延迟函数,则该函数不会阻塞,立即返回一个future_status::deferred值。

8. wait_until函数:(1). 等待共享状态在指定的时间点(time point)准备就绪。(2). 如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪或已达到指定的时间点。(3).此函数的返回值类型为枚举类future_status。(4).如果共享状态包含了一个延迟函数,则该函数不会阻塞,立即返回一个future_status::deferred值。

详细用法见下面的测试代码,下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:


  
  1. #include "future.hpp"
  2. #include <iostream>
  3. #include <future>
  4. #include <chrono>
  5. #include <utility>
  6. #include <thread>
  7. namespace future_ {
  8. ///////////////////////////////////////////////////////////
  9. // reference: https://en.cppreference.com/w/cpp/thread/shared_future
  10. int test_shared_future_1()
  11. {
  12. std::promise< void> ready_promise, t1_ready_promise, t2_ready_promise;
  13. // 通过std::future移动构造std::shared_future对象,t1_ready_promise和t2_ready_promise均会用到ready_future
  14. std::shared_future< void> ready_future(ready_promise.get_future());
  15. std::chrono::time_point< std::chrono::high_resolution_clock> start;
  16. auto fun1 = [&, ready_future]() -> std::chrono::duration< double, std::milli> {
  17. t1_ready_promise.set_value();
  18. ready_future.wait(); // waits for the signal from main()
  19. return std::chrono::high_resolution_clock::now() - start;
  20. };
  21. auto fun2 = [&, ready_future]() -> std::chrono::duration< double, std::milli> {
  22. t2_ready_promise.set_value();
  23. ready_future.wait(); // waits for the signal from main()
  24. return std::chrono::high_resolution_clock::now() - start;
  25. };
  26. auto fut1 = t1_ready_promise.get_future();
  27. auto fut2 = t2_ready_promise.get_future();
  28. auto result1 = std::async( std::launch::async, fun1);
  29. auto result2 = std::async( std::launch::async, fun2);
  30. // wait for the threads to become ready
  31. fut1.wait();
  32. fut2.wait();
  33. // the threads are ready, start the clock
  34. start = std::chrono::high_resolution_clock::now();
  35. // signal the threads to go
  36. ready_promise.set_value();
  37. std:: cout << "Thread 1 received the signal " << result1.get().count() << " ms after start\n"
  38. << "Thread 2 received the signal " << result2.get().count() << " ms after start\n";
  39. return 0;
  40. }
  41. ///////////////////////////////////////////////////////////
  42. // reference: https://en.cppreference.com/w/cpp/thread/shared_future/wait
  43. int fib(int n)
  44. {
  45. if (n < 3) return 1;
  46. else return fib(n - 1) + fib(n - 2);
  47. }
  48. int test_shared_future_2()
  49. {
  50. // 将std::shared_future<int>调整为std::future<int>也是正确的
  51. std::shared_future< int> f1 = std::async( std::launch::async, []() { return fib( 20); });
  52. std::shared_future< int> f2 = std::async( std::launch::async, []() { return fib( 25); });
  53. std:: cout << "waiting...\n";
  54. f1.wait();
  55. f2.wait();
  56. std:: cout << "f1: " << f1.get() << '\n';
  57. std:: cout << "f2: " << f2.get() << '\n';
  58. return 0;
  59. }
  60. ///////////////////////////////////////////////////////////
  61. // reference: https://en.cppreference.com/w/cpp/thread/shared_future/wait_for
  62. int test_shared_future_3()
  63. {
  64. // 将std::shared_future<int>调整为std::future<int>也是正确的
  65. std::shared_future< int> future = std::async( std::launch::async, [](){
  66. std::this_thread::sleep_for( std::chrono::seconds( 3));
  67. return 8;
  68. });
  69. std:: cout << "waiting...\n";
  70. std::future_status status;
  71. do {
  72. status = future.wait_for( std::chrono::seconds( 1));
  73. if (status == std::future_status::deferred) {
  74. std:: cout << "deferred\n";
  75. } else if (status == std::future_status::timeout) {
  76. std:: cout << "timeout\n";
  77. } else if (status == std::future_status::ready) {
  78. std:: cout << "ready!\n";
  79. }
  80. } while (status != std::future_status::ready);
  81. std:: cout << "result is " << future.get() << '\n';
  82. return 0;
  83. }
  84. } // namespace future_

GitHubhttps://github.com/fengbingchun/Messy_Test


转载:https://blog.csdn.net/fengbingchun/article/details/104118831
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场