1. 程式人生 > >C++多執行緒中的future(期望)

C++多執行緒中的future(期望)

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::futureget()成員獲取。

建構函式:

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;
}