[C++11 並發編程] 13 使用期望等待一次性事件

來源:互聯網
上載者:User

標籤:c++   並發   async   future   

C++標準庫使用期望(future)來支援一次性事件的等待。要等待某種一次性事件的線程可以擷取一個代表該該事件的期望。這個線程可以每隔一段事件周期性的查詢這個期望。此外,這個線程也可以繼續做其它的處理,直到需要等待這個一次性事件才被掛起。通到期望還可以可以傳遞資料。

C++標準庫提供了兩種期望unique future(std::future<>)和shared futures(std::shared_future<>),都聲明在<future>庫標頭檔中。std::future執行個體只能關聯到一個事件。而多個std::shared_future可以關聯到同一個事件。共用期望所關聯的事件發生時,所有期望執行個體都將同時被喚醒,而去訪問這個事件。由於期望可以關聯資料,所以期望都是模版類,沒有資料關聯到期望時,就可以使用std::future<void>和std::shared_future<void>。雖然期望被用於線程間通訊,但是期望對象並不支援同步的訪問,我們需要使用mutex之類的機制,來保護不同線程對它們的訪問。

假設我們有一個需要較長時間的計算操作,我們要使用它的計算結果,在需要這個計算結果之前,我們可以做一些其它的操作。我們可以啟動一個新的線程來做計算。std:;thread沒有直接的機制來滿足我們的需求。這裡可以使用std::async函數模版來實現這個功能。

std::async可以啟動一個非同步線程,我們無需像使用thread一樣,立即開始等待這個非同步線程執行結束,std::async會返回一個期望對象,這個對象最終會用來儲存非同步線程的返回結果。當我們需要這個結果時,對期望對象調用wait就可以讓線程阻塞,直到期望準備好。例子如下:

#include <future>#include <iostream>int find_the_answer_to_ltuae(){    return 42;}void do_other_stuff(){}int main(){    std::future<int> the_answer=std::async(find_the_answer_to_ltuae);    do_other_stuff();    std::cout<<"The answer is "<<the_answer.get()<<std::endl;}
std::async允許我們傳遞額外的參數給函數。如果第一個參數是一個成員函數指標,第二個參數就是成員函數對應的對象的指標,其它的參數就是傳遞給成員函數的參數。否則,第二個及後續的參數就是傳遞給作為第一個參數的函數或callable對象的參數。
#include <string>#include <future>struct X{    void foo(int,std::string const&);    std::string bar(std::string const&);};X x;// 調用x->foo(42, "hello");auto f1=std::async(&X::foo,&x,42,"hello");// 調用tmpx.bar("goodbye"); tmpx是x的拷貝auto f2=std::async(&X::bar,x,"goodbye");struct Y{    double operator()(double);};Y y;// 調用tmpy(3.141);tmpy是從Y()移動構造而來auto f3=std::async(Y(),3.141);// 調用y(2.718);auto f4=std::async(std::ref(y),2.718);X baz(X&);// 調用baz(x);auto f6=std::async(baz,std::ref(x));class move_only{public:    move_only();    move_only(move_only&&);    move_only(move_only const&) = delete;    move_only& operator=(move_only&&);    move_only& operator=(move_only const&) = delete;    void operator()();};// 調用tmp();tmp是通過std::move(move_only)構造而來auto f5=std::async(move_only());
預設情況下,我們需要自己決定std::async是啟動一個新的線程,還是在等待期望時同步的執行。我們可以通過傳遞給std::async的參數來控制它。參數類型為std::launch:

  • std::launch::deferred表示函數調用被延遲到期望的wait()或get()被調用時。
  • std::launch::async表示啟動新的線程來執行函數。
  • std::launch::deferred | std::launch::async則表示通過具體實現來控制這個行為。

std::async模式使用第三種行為。

// 啟動新的線程auto f6=std::async(std::launch::async, Y(), 1.2);// 在wait()或get()被調用時執行auto f7=std::async(std::launch::deferred, baz, std::ref(x));// 取決於實現auto f8=std::async(std::launch::deferred | std::launch::async,   baz, std::ref(x));auto f9=std::async(baz, std::ref(x));// 調用被延遲的函數f7.wait();
這不是讓一個std::future與一個任務執行個體相關聯的唯一方式;你也可以將任務封裝入一個std::packaged_task<>執行個體中,或使用std::promise<>類型模板。



著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

[C++11 並發編程] 13 使用期望等待一次性事件

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.