C++多執行緒中的future(期望)
阿新 • • 發佈:2018-11-19
Providers
std::promise
和std::future
配合使用,給std::future
傳遞期望值,下面是最簡單的一個用法:
#include <iostream>
#include <functional>
#include <thread>
#include <future>
// 一定要注意是傳遞引用
void print_int(std::future<int>& fut) {
auto x = fut.get(); // 如果future中沒有值,那麼在這裡一直等待
std:: cout << "value: " << x << std::endl;
}
int main() {
std::promise<int> prom;
std::future<int> fut = prom.get_future(); // 獲取承諾的future
std::thread th1(print_int, std::ref(fut));
std::cout << "Please input a value:";
int n;
std::cin >> n;
prom.set_value(n); // 把資料傳遞給承諾的future中
th1.join();
return 0;
}
packaged_task
這是一個更高階的封裝,封裝的元素是可呼叫物件,對比上面的promise
,那個是僅僅封裝數值的。
構造方式:
template <class T> packaged_task; // undefined
template <class Ret, class... Args> class packaged_task<Ret(Args...)>;
例項說明:
#include <iostream>
#include <future>
#include <chrono>
#include <thread>
int countdown(int from, int to) {
for(int i = from; i != to; --i) {
std::cout << i << std::endl;
// 執行緒休眠1秒
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);
std::future<int>ret = tsk.get_future();
// 構造執行緒開始執行任務,注意是移動構造
std::thread th(std::move(tsk), 10, 0);
// 沒有返回結果時,當前執行緒就一直阻塞
int value = ret.get();
std::cout << "The countdown lasted for " << value << " seconds\n";
th.join();
return 0;
}
Futures
兩者只支援移動賦值,無法進行復制操作。
std::future
期望,用於同步資料或者是等待其他執行緒的非同步通訊結果。
template <class T> future;
template <class R&> future<R&>; // specialization : T is a reference type (R&)
template <> future<void>; // specialization : T is void
成員函式:
T get();
R& future<R&>::get(); // when T is a reference type (R&)
void future<void>::get(); // when T is void
具體例項參照上面。在不呼叫wait
類函式的情況下,如果還沒計算完成,就一直等待到計算完成。
void wait() const;
等待計算結果完畢,呼叫完成該函式後,再次呼叫get()
函式,僅僅是返回一個狀態,例如:
// future::wait
#include <iostream> // std::cout
#include <future> // std::async, std::future
#include <chrono> // 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;
}
template <class Rep, class Period>
future_status wait_for (const chrono::duration<Rep,Period>& rel_time) const;
等待計算完畢或者到達指定時間,之後程式繼續執行,rel_time
是指的時間間隔。
template <class Clock, class Duration>
future_status wait_until (const chrono::time_point<Clock,Duration>& abs_time) const;
類似於wait_for
,不過abs_time
是指的絕對時間點
std::shared_future
包含了std::future
的所有功能,但是可以進行復制操作。
Functions
async
一個非同步呼叫,不等待計算結果,立刻返回一個std::future
型別。計算的結果由返回的std::future
的get()
成員獲取。
建構函式:
template <class Fn, class... Args>
future<typename result_of<Fn(Args...)>::type>
async (Fn&& fn, Args&&... args);
template <class Fn, class... Args>
future<typename result_of<Fn(Args...)>::type>
async (launch policy, Fn&& fn, Args&&... args);
一般只使用第一個,第二個的策略具體查詢手冊即可。
程式碼例項:
#include <iostream>
#include <future>
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() {
std::future<bool>fut = std::async(is_prime, 313222313);
std::cout << "Checking whether 313222313 is prime.\n";
bool ret = fut.get(); // 獲取結果,在計算出結果之前,這個會一直阻塞
if(ret) {
std::cout << "It is prime !\n";
} else {
std::cout << "It is not prime !\n";
}
return 0;
}