小言_互联网的博客

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

400人阅读  评论(0)

C++11中的std::async是个模板函数。std::async异步调用函数,在某个时候以Args作为参数(可变长参数)调用Fn,无需等待Fn执行完成就可返回,返回结果是个std::future对象。Fn返回的值可通过std::future对象的get成员函数获取。一旦完成Fn的执行,共享状态将包含Fn返回的值并ready。

std::async有两个版本:

1.无需显示指定启动策略,自动选择,因此启动策略是不确定的,可能是std::launch::async,也可能是std::launch::deferred,或者是两者的任意组合,取决于它们的系统和特定库实现。

2.允许调用者选择特定的启动策略。

std::async的启动策略类型是个枚举类enum class launch,包括:

1. std::launch::async:异步,启动一个新的线程调用Fn,该函数由新线程异步调用,并且将其返回值与共享状态的访问点同步。

2. std::launch::deferred:延迟,在访问共享状态时该函数才被调用。对Fn的调用将推迟到返回的std::future的共享状态被访问时(使用std::future的wait或get函数)。

参数Fn:可以为函数指针、成员指针、任何类型的可移动构造的函数对象(即类定义了operator()的对象)。Fn的返回值或异常存储在共享状态中以供异步的std::future对象检索。

参数Args:传递给Fn调用的参数,它们的类型应是可移动构造的。

返回值:当Fn执行结束时,共享状态的std::future对象准备就绪。std::future的成员函数get检索的值是Fn返回的值。当启动策略采用std::launch::async时,即使从不访问其共享状态,返回的std::future也会链接到被创建线程的末尾。在这种情况下,std::future的析构函数与Fn的返回同步。

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

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


  
  1. #include "future.hpp"
  2. #include <iostream>
  3. #include <future>
  4. #include <chrono>
  5. #include <utility>
  6. #include <thread>
  7. #include <functional>
  8. #include <memory>
  9. #include <exception>
  10. #include <numeric>
  11. #include <vector>
  12. #include <cmath>
  13. #include <string>
  14. #include <mutex>
  15. namespace future_ {
  16. ///////////////////////////////////////////////////////////
  17. // reference: http://www.cplusplus.com/reference/future/async/
  18. int test_async_1()
  19. {
  20. auto is_prime = []( int x) {
  21. std:: cout << "Calculating. Please, wait...\n";
  22. for ( int i = 2; i < x; ++i) if (x%i == 0) return false;
  23. return true;
  24. };
  25. // call is_prime(313222313) asynchronously:
  26. std::future< bool> fut = std::async(is_prime, 313222313);
  27. std:: cout << "Checking whether 313222313 is prime.\n";
  28. // ...
  29. bool ret = fut.get(); // waits for is_prime to return
  30. if (ret) std:: cout << "It is prime!\n";
  31. else std:: cout << "It is not prime.\n";
  32. return 0;
  33. }
  34. ///////////////////////////////////////////////////////////
  35. // reference: http://www.cplusplus.com/reference/future/launch/
  36. int test_async_2()
  37. {
  38. auto print_ten = []( char c, int ms) {
  39. for ( int i = 0; i < 10; ++i) {
  40. std::this_thread::sleep_for( std::chrono::milliseconds(ms));
  41. std:: cout << c;
  42. }
  43. };
  44. std:: cout << "with launch::async:\n";
  45. std::future< void> foo = std::async( std::launch::async, print_ten, '*', 100);
  46. std::future< void> bar = std::async( std::launch::async, print_ten, '@', 200);
  47. // async "get" (wait for foo and bar to be ready):
  48. foo.get(); // 注:注释掉此句,也会输出'*'
  49. bar.get();
  50. std:: cout << "\n\n";
  51. std:: cout << "with launch::deferred:\n";
  52. foo = std::async( std::launch::deferred, print_ten, '*', 100);
  53. bar = std::async( std::launch::deferred, print_ten, '@', 200);
  54. // deferred "get" (perform the actual calls):
  55. foo.get(); // 注:注释掉此句,则不会输出'**********'
  56. bar.get();
  57. std:: cout << '\n';
  58. return 0;
  59. }
  60. ///////////////////////////////////////////////////////////
  61. // reference: https://en.cppreference.com/w/cpp/thread/async
  62. std::mutex m;
  63. struct X {
  64. void foo(int i, const std::string& str) {
  65. std::lock_guard< std::mutex> lk(m);
  66. std:: cout << str << ' ' << i << '\n';
  67. }
  68. void bar(const std::string& str) {
  69. std::lock_guard< std::mutex> lk(m);
  70. std:: cout << str << '\n';
  71. }
  72. int operator()(int i) {
  73. std::lock_guard< std::mutex> lk(m);
  74. std:: cout << i << '\n';
  75. return i + 10;
  76. }
  77. };
  78. template < typename RandomIt>
  79. int parallel_sum(RandomIt beg, RandomIt end)
  80. {
  81. auto len = end - beg;
  82. if (len < 1000)
  83. return std::accumulate(beg, end, 0);
  84. RandomIt mid = beg + len / 2;
  85. auto handle = std::async( std::launch::async, parallel_sum<RandomIt>, mid, end);
  86. int sum = parallel_sum(beg, mid);
  87. return sum + handle.get();
  88. }
  89. int test_async_3()
  90. {
  91. std:: vector< int> v( 10000, 1);
  92. std:: cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
  93. X x;
  94. // Calls (&x)->foo(42, "Hello") with default policy:
  95. // may print "Hello 42" concurrently or defer execution
  96. auto a1 = std::async(&X::foo, &x, 42, "Hello");
  97. // Calls x.bar("world!") with deferred policy
  98. // prints "world!" when a2.get() or a2.wait() is called
  99. auto a2 = std::async( std::launch::deferred, &X::bar, x, "world!");
  100. // Calls X()(43); with async policy
  101. // prints "43" concurrently
  102. auto a3 = std::async( std::launch::async, X(), 43);
  103. a2.wait(); // prints "world!"
  104. std:: cout << a3.get() << '\n'; // prints "53"
  105. return 0;
  106. } // if a1 is not done at this point, destructor of a1 prints "Hello 42" here
  107. ///////////////////////////////////////////////////////////
  108. // reference: https://thispointer.com/c11-multithreading-part-9-stdasync-tutorial-example/
  109. int test_async_4()
  110. {
  111. using namespace std::chrono;
  112. auto fetchDataFromDB = []( std:: string recvdData) {
  113. // Make sure that function takes 5 seconds to complete
  114. std::this_thread::sleep_for(seconds( 5));
  115. //Do stuff like creating DB Connection and fetching Data
  116. return "DB_" + recvdData;
  117. };
  118. auto fetchDataFromFile = []( std:: string recvdData) {
  119. // Make sure that function takes 5 seconds to complete
  120. std::this_thread::sleep_for(seconds( 5));
  121. //Do stuff like fetching Data File
  122. return "File_" + recvdData;
  123. };
  124. // Get Start Time
  125. system_clock::time_point start = system_clock::now();
  126. std::future< std:: string> resultFromDB = std::async( std::launch::async, fetchDataFromDB, "Data");
  127. //Fetch Data from File
  128. std:: string fileData = fetchDataFromFile( "Data");
  129. //Fetch Data from DB
  130. // Will block till data is available in future<std::string> object.
  131. std:: string dbData = resultFromDB.get();
  132. // Get End Time
  133. auto end = system_clock::now();
  134. auto diff = duration_cast < std::chrono::seconds> (end - start).count();
  135. std:: cout << "Total Time Taken = " << diff << " Seconds" << std:: endl;
  136. //Combine The Data
  137. std:: string data = dbData + " :: " + fileData;
  138. //Printing the combined Data
  139. std:: cout << "Data = " << data << std:: endl;
  140. return 0;
  141. }
  142. } // namespace future_

GitHubhttps://github.com/fengbingchun/Messy_Test


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