C++11中std::async的使用
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:
#include "future.hpp"
#include <iostream>
#include <future>
#include <chrono>
#include <utility>
#include <thread>
#include <functional>
#include <memory>
#include <exception>
#include <numeric>
#include <vector>
#include <cmath>
#include <string>
#include <mutex>namespace future_ {///
// reference: http://www.cplusplus.com/reference/future/async/
int test_async_1()
{auto 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;};// 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 returnif (ret) std::cout << "It is prime!\n";else std::cout << "It is not prime.\n";return 0;
}///
// reference: http://www.cplusplus.com/reference/future/launch/
int test_async_2()
{auto print_ten = [](char c, int ms) {for (int i = 0; i < 10; ++i) {std::this_thread::sleep_for(std::chrono::milliseconds(ms));std::cout << c;}};std::cout << "with launch::async:\n";std::future<void> foo = std::async(std::launch::async, print_ten, '*', 100);std::future<void> bar = std::async(std::launch::async, print_ten, '@', 200);// async "get" (wait for foo and bar to be ready):foo.get(); // 注:注釋掉此句,也會輸出'*'bar.get();std::cout << "\n\n";std::cout << "with launch::deferred:\n";foo = std::async(std::launch::deferred, print_ten, '*', 100);bar = std::async(std::launch::deferred, print_ten, '@', 200);// deferred "get" (perform the actual calls):foo.get(); // 注:注釋掉此句,則不會輸出'**********'bar.get();std::cout << '\n';return 0;
}///
// reference: https://en.cppreference.com/w/cpp/thread/async
std::mutex m;struct X {void foo(int i, const std::string& str) {std::lock_guard<std::mutex> lk(m);std::cout << str << ' ' << i << '\n';}void bar(const std::string& str) {std::lock_guard<std::mutex> lk(m);std::cout << str << '\n';}int operator()(int i) {std::lock_guard<std::mutex> lk(m);std::cout << i << '\n';return i + 10;}
};template <typename RandomIt>
int parallel_sum(RandomIt beg, RandomIt end)
{auto len = end - beg;if (len < 1000)return std::accumulate(beg, end, 0);RandomIt mid = beg + len / 2;auto handle = std::async(std::launch::async, parallel_sum<RandomIt>, mid, end);int sum = parallel_sum(beg, mid);return sum + handle.get();
}int test_async_3()
{std::vector<int> v(10000, 1);std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';X x;// Calls (&x)->foo(42, "Hello") with default policy:// may print "Hello 42" concurrently or defer executionauto a1 = std::async(&X::foo, &x, 42, "Hello");// Calls x.bar("world!") with deferred policy// prints "world!" when a2.get() or a2.wait() is calledauto a2 = std::async(std::launch::deferred, &X::bar, x, "world!");// Calls X()(43); with async policy// prints "43" concurrentlyauto a3 = std::async(std::launch::async, X(), 43);a2.wait(); // prints "world!"std::cout << a3.get() << '\n'; // prints "53"return 0;
} // if a1 is not done at this point, destructor of a1 prints "Hello 42" here///
// reference: https://thispointer.com/c11-multithreading-part-9-stdasync-tutorial-example/
int test_async_4()
{using namespace std::chrono;auto fetchDataFromDB = [](std::string recvdData) {// Make sure that function takes 5 seconds to completestd::this_thread::sleep_for(seconds(5));//Do stuff like creating DB Connection and fetching Datareturn "DB_" + recvdData;};auto fetchDataFromFile = [](std::string recvdData) {// Make sure that function takes 5 seconds to completestd::this_thread::sleep_for(seconds(5));//Do stuff like fetching Data Filereturn "File_" + recvdData;};// Get Start Timesystem_clock::time_point start = system_clock::now();std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "Data");//Fetch Data from Filestd::string fileData = fetchDataFromFile("Data");//Fetch Data from DB// Will block till data is available in future<std::string> object.std::string dbData = resultFromDB.get();// Get End Timeauto end = system_clock::now();auto diff = duration_cast <std::chrono::seconds> (end - start).count();std::cout << "Total Time Taken = " << diff << " Seconds" << std::endl;//Combine The Datastd::string data = dbData + " :: " + fileData;//Printing the combined Datastd::cout << "Data = " << data << std::endl;return 0;
}} // namespace future_
GitHub:https://github.com/fengbingchun/Messy_Test
總結
以上是生活随笔為你收集整理的C++11中std::async的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++11中std::packaged_
- 下一篇: 从FFmpeg 4. 2源码中提取dsh