bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

C++多線程:std::promise-創新互聯

C++ 多線程09:std::promise

創新互聯公司堅持“要么做到,要么別承諾”的工作理念,服務領域包括:成都做網站、網站設計、外貿營銷網站建設、企業官網、英文網站、手機端網站、網站推廣等服務,滿足客戶于互聯網時代的天山網站設計、移動媒體設計的需求,幫助企業找到有效的互聯網解決方案。努力成為您成熟可靠的網絡建設合作伙伴!文章目錄
  • C++ 多線程09:std::promise
      • 概念
      • 默認構造函數
      • 帶分配器的構造函數
      • 移動構造函數
      • 移動賦值操作符
      • swap成員函數
      • 析構函數
      • get_future成員函數
      • set_value成員函數
      • set_value_at_thread_exit 成員函數
      • set_exception 成員函數
      • set_exception_at_thread_exit 成員函數
    • 從未設值
    • 存儲自定義異常
    • `std::promise`
    • std::promise所在線程退出時
    • std::future_errc

概念

std::promise是一個模板類:templateclass promise。其泛型參數ResultTypestd::promise對象保存的值的類型,例如std::promiseResultType可以是void類型。std::promise類型模板提供設置異步結果的方法,這樣其他線程就可以通過std::future實例來讀取該結果。std::promisestd::future合作共同實現了多線程間通信。

在構造std::promise對象時,該對象與新的共享狀態(shared state)關聯。通過調用std::promiseget_future函數,可以將該共享狀態與std::future對象關聯。調用get_future之后,兩個對象共享相同的共享狀態:std::promise對象是異步提供程序(asynchronous provider),應在某個時刻為共享狀態設置一個值。std::future對象是個異步返回對象,可以檢索共享狀態的值,并在必要時等待其準備就緒。 需要注意的是:set_value只能被調用一次,多次調用會拋出std::future_error異常。事實上std::promise::set_xxx函數會改變std::promise的狀態為ready,再次調用時發現狀態已要是reday了,則拋出異常。

std::promise實例是可以MoveConstructible(移動構造)和MoveAssignable(移動賦值),但是不能CopyConstructible(拷貝構造)和CopyAssignable(拷貝賦值)。

類型定義

templateclass promise
{public:
  promise();
  promise(promise&&) noexcept;
  ~promise();
  promise& operator=(promise&&) noexcept;

  templatepromise(std::allocator_arg_t, Allocator const&);

  promise(promise const&) = delete;
  promise& operator=(promise const&) = delete;

  void swap(promise& ) noexcept;
  
  std::futureget_future();

  void set_value(see description);
  void set_exception(std::exception_ptr p);
};
復制代碼
默認構造函數

通過訪問新的空共享狀態來構造一個std::promise對象(The object is initialized with access to a new empty shared state)。并且使用ResultType類型的相關異步結果來構造std::promise實例,不過異步結果并未就緒。當沒有足夠內存為異步結果進行分配,那么將拋出std::bad_alloc型異常。

帶分配器的構造函數

構造一個std::promise對象,使用提供的分配器來為相關異步結果分配內存。

templatepromise(std::allocator_arg_t, Allocator const& alloc);
復制代碼
移動構造函數
promise(promise&& other) noexcept;
復制代碼

通過另一個已存在對象,構造一個std::promise對象。將已存在對象中的共享狀態以及相關異步結果的所有權轉移到新創建的std::promise對象當中。之后,other將無關聯異步結果。

#include   // std::cout
#include // std::thread
#include // std::promise, std::future
#includestd::promiseprom;

void print_global_promise () {std::futurefut = prom.get_future();
    int x = fut.get();
    std::cout<< "value: "<< x<< '\n';  // value is: 20
}

int main ()
{std::thread th1(print_global_promise);
	// 等待線程th1線跑獲調用prom.get_future()
    std::this_thread::sleep_for(std::chrono::seconds(1));
    // 將prom所有權將轉移到新創建的對象prom2上
    std::promiseprom2(std::move(prom));
	// 對prom2進行設值,在之前的prom的get也能獲取到,最終輸出20
    prom2.set_value (20);
    th1.join();
    return 0;
}
復制代碼
移動賦值操作符
promise& operator=(promise&& other) noexcept;
復制代碼

在兩個std::promise實例中轉移異步結果的所有權。在other和*this之間進行異步結果所有權的轉移。當*this已經有關聯的異步結果,那么該異步結果的狀態將會為就緒態,且伴隨一個std::future_error類型異常,錯誤碼為std::future_errc::broken_promise。

將other中關聯的異步結果轉移到*this當中后。other中將無關聯異步結果。返回*this。

#include   // std::cout
#include // std::thread
#include // std::promise, std::future

std::promiseprom;

void print_global_promise () {std::futurefut = prom.get_future();
    int x = fut.get();
    std::cout<< "value: "<< x<< '\n';
}

int main () {std::thread th1(print_global_promise);
    prom.set_value(10);
    th1.join();

    prom = std::promise();    // prom 被move賦值為一個新的 promise 對象.

    std::thread th2 (print_global_promise);
    prom.set_value (20);
    th2.join();

    return 0;
}
復制代碼
swap成員函數

將兩個std::promise實例中的關聯異步結果進行交換。

void swap(promise& other);
復制代碼

交換other和*this當中的關聯異步結果。當swap使用other時,other中的異步結果就會與*this中關聯異步結果相交換。二者返回來亦然。

析構函數

放棄(abandon)共享狀態并銷毀std::promise對象。當*this具有關聯的異步結果,并且結果中沒有存儲值或異常(從未調用set_xx函數),那么結果將會置為就緒,伴隨一個std::future_error異常,錯誤碼為std::future_errc::broken_promise。可以看下面單獨章節說明例子。

get_future成員函數

返回一個與promise對象的共享狀態關聯的std::future對象。

std::futureget_future();
復制代碼

首先,*this要具有關聯異步結果。最后返回與*this關聯異步結果關聯的std::future實例。

std::future已經通過get_future()獲取過了,第二次獲取將會拋出一個std::future_error類型異常,伴隨的錯誤碼為std::future_errc::future_already_retrieved(Only one future object can be retrieved for each promise shared state)。 調用此函數后,promise應在某個時候使其共享狀態準備就緒(通過設置值或異常),否則將在銷毀時自動準備就緒并包含一個std::future_error類型的異常。

#include   // std::cout
#include // std::promise, std::future


int main () {std::promiseprom; // 生成一個 std::promise對象.
    std::futurefut = prom.get_future(); // 和 future 關聯.
    try {std::futurefut2 = prom.get_future(); // 多次與 future 關聯.
    } catch (std::exception &e) {std::cout<< "exception: "<< e.what()<< '\n'; 
    }

    return 0;
}
復制代碼

輸出:

exception: std::future_error: Future already retrieved
復制代碼
set_value成員函數

存儲一個值到與*this關聯的異步結果中。

void promise::set_value();
void promise::set_value(R& r);
void promise::set_value(R const& r);
void promise::set_value(R&& r);
復制代碼

首先,*this要具有關聯異步結果。最后,當ResultType不是void型,就存儲r到*this相關的異步結果當中。*this相關的異步結果的狀態為就緒,且將值存入。任意等待異步結果的阻塞線程將解除阻塞。

如果異步結果已經存有一個值或一個異常,那么再次調用該函數將拋出std::future_error型異常,伴隨錯誤碼為std::future_errc::promise_already_satisfied

#include   // std::cout
#include // std::ref
#include // std::thread
#include // std::promise, std::future

void print_int(std::future& fut) {int x = fut.get(); // 獲取共享狀態的值.
    std::cout<< "value: "<< x<< '\n'; // 打印 value: 10.
}

int main () {std::promiseprom; // 生成一個 std::promise對象.
    std::futurefut = prom.get_future(); // 和 future 關聯.
    std::thread t(print_int, std::ref(fut)); // 將 future 交給另外一個線程t.
    prom.set_value(10); // 設置共享狀態的值, 此處和線程t保持同步.

    try {prom.set_value(20); // 多次set_value.
    } catch (std::exception &e) {std::cout<< "exception: "<< e.what()<< '\n'; 
    }

    t.join();
    return 0;
}
復制代碼

輸出:

value: 10
exception: std::future_error: Promise already satisfied
復制代碼
set_value_at_thread_exit 成員函數

存儲一個值到與*this關聯的異步結果中,標記異步結果為“已存儲值”,但未就緒,直到線程退出時,異步結果的狀態才會被設置為就緒 (Stores the exception pointer p in the shared state without making it ready immediately. Instead, it will be made ready automatically at thread exit, once all objects of thread storage duration have been destroyed)。

void promise::set_value_at_thread_exit();
void promise::set_value_at_thread_exit(R& r);
void promise::set_value_at_thread_exit(R const& r);
void promise::set_value_at_thread_exit(R&& r);
復制代碼

當異步結果已經存有一個值或一個異常,那么將拋出std::future_error型異常,伴隨錯誤碼為std::future_errc::promise_already_satisfied。

set_exception 成員函數

存儲一個異常到與*this關聯的異步結果中。

void set_exception(std::exception_ptr e);
復制代碼

首先,*this具有關聯異步結果。然后將e存儲到*this相關的異步結果中。在存儲異常后,*this相關的異步結果的狀態將置為就緒。任何等待異步結果的阻塞線程將解除阻塞。

當異步結果已經存有一個值或一個異常,那么將拋出std::future_error型異常,伴隨錯誤碼為std::future_errc::promise_already_satisfied

#include#includeint main() {std::promisep;
    std::futuref = p.get_future();
 
    try {// 可能拋出的代碼
        throw std::runtime_error("Example");
    } catch(...) {try {// 存儲任何拋出的異常于 promise
            p.set_exception(std::current_exception());
        } catch(...) {} // set_exception() 亦可能拋出
    }

    // 存儲任何拋出的異常于 promise,自定義異常需要使用make_exception_ptr轉換一下
    // p.set_exception(std::make_exception_ptr(std::runtime_error("Example")));

    try {std::cout<< f.get();
    } catch(const std::exception& e) {std::cout<< "Exception from the thread: "<< e.what()<< '\n';
    }
}
復制代碼

輸出:

Exception from the thread: Example
復制代碼
set_exception_at_thread_exit 成員函數

存儲一個異常到共享狀態中,而不立即使狀態就緒,直到當前線程退出,銷毀所有擁有線程局域存儲期的變量后,異步結果才被置為就緒。

void set_exception_at_thread_exit(std::exception_ptr e);
復制代碼

*this無共享狀態。伴隨錯誤碼為std::future_errc::no_state。當異步結果已經存有一個值或一個異常,那么將拋出std::future_error型異常,伴隨錯誤碼為std::future_errc::promise_already_satisfied。

從未設值

如果promise對象直到析構銷毀時,都沒有調用set_xx接口設置過任何值,則promise會在析構時自動設置為std::future_error錯誤異常,這會造成std::future.get立刻解除阻塞并拋出std::future_error異常。

#include// std::cout, std::endl
#include// std::thread
#include// std::promise, std::future
#include// seconds
using namespace std::chrono;

void future_get(std::futurefuture) {try {future.get();
    } catch(std::future_error &e) {std::cerr<< e.code()<< "\n"<< e.what()<< std::endl;
    }
}

int main() {std::thread thread;
    {// 如果promise不設置任何值
        // 則在promise析構時會自動設置為future_error
        // 這會造成future.get拋出該異常
        std::promisepromise;
        thread = std::thread(future_get, promise.get_future());
    }
    std::cout<< "promise destory here"<< std::endl;
    thread.join();

    return 0;
}
復制代碼

輸出:

future:4
std::future_error: Broken promise
promise destory here
復制代碼
存儲自定義異常

通過std::promise::set_exception函數可以設置自定義異常,該異常最終會被傳遞到std::future,并在其get函數中被拋出。

自定義異常可以通過位于頭文件exception下的std::make_exception_ptr函數轉化為std::exception_ptr

#include#include#include#include// std::make_exception_ptr


struct MyException : public std::exception {const char * what () const throw ()
  {return "Test promise exception";
  }
};


void catch_exception(std::future&future) {try {future.get();
    } catch (MyException &e) {std::cout<< "MyException: "<< e.what()<< std::endl;
    }
}

int main() {std::promisepromise;
    std::futurefuture = promise.get_future();

    std::thread thread(catch_exception, std::ref(future));
    // 自定義異常需要使用make_exception_ptr轉換一下
    promise.set_exception(std::make_exception_ptr(MyException()));
    
    thread.join();
    return 0;
}
復制代碼

輸出:

MyException: Test promise exception
復制代碼
std::promise

std::promise是合法的,它是std::promise的特例化。此時std::promise.set_value不接受任何參數,僅用于通知關聯的std::future.get()解除阻塞,void 特化,僅用于交流無狀態事件。

#include   // std::cout
#include // std::ref
#include // std::thread
#include // std::promise, std::future

void print_void(std::future& fut) {fut.get(); // 獲取共享狀態的值void.
    std::cout<< "value: void"<< '\n'; // 打印 value: 10.
}

int main () {std::promiseprom; // 生成一個 std::promise對象.
    std::futurefut = prom.get_future(); // 和 future 關聯.
    std::thread t(print_void, std::ref(fut)); // 將 future 交給另外一個線程t.
    prom.set_value(); // 設置共享狀態的值, 此處和線程t保持同步.
    t.join();
    return 0;
}
復制代碼
std::promise所在線程退出時

std::promise支持定制線程退出時的行為:

std::promise::set_value_at_thread_exit線程退出時,std::future收到通過該函數設置的值。std::promise::set_exception_at_thread_exit線程退出時,std::future則拋出該函數指定的異常。

#include#include#include#includestd::time_t now() {auto t0 = std::chrono::system_clock::now();
    std::time_t time_t_today = std::chrono::system_clock::to_time_t(t0);
    return time_t_today;  // seconds
}

int main() {using namespace std::chrono_literals;
    std::promisep;
    std::futuref = p.get_future();

    std::thread([&p] {  std::this_thread::sleep_for(1s);
          p.set_value_at_thread_exit(9);
    }).detach();
 
    std::cout<< now()<< "->Waiting...\n"<< std::flush;
    f.wait();
    std::cout<< now()<< "->Done!\nResult is: "<< f.get()<< '\n';
}
復制代碼

輸出:

1647995534->Waiting...
1647995535->Done!
Result is: 9
復制代碼

從上面的輸出可以看到,waiting和Done之間是有間隔1s鐘的,也就是說set_value_at_thread_exit確實需要等線程結束后才會設值get為就緒解除阻塞。

std::future_errc

下面簡單介紹一下std::future_errc類型,future_errc 類枚舉 : 是 future_error 類報告的所有錯誤提供符號名稱。future_errc枚舉類型的值可用于創建error_condition對象,可以用于與future_error異常返回的值進行比較。

名稱示意
broken_promise0與其關聯的 std::promise 生命周期提前結束。
future_already_retrieved1重復調用 get() 函數。
promise_already_satisfied2與其關聯的 std::promise 重復 set。
no_state4無共享狀態。
#include // std::cerr
#include   // std::promise, std::future_error, std::future_errc

int main () {std::promiseprom;

  try {prom.get_future();
    prom.get_future();   // throws std::future_error with future_already_retrieved
  }
  catch (std::future_error& e) {if (e.code() == std::make_error_condition(std::future_errc::future_already_retrieved))
    std::cerr<< "[future already retrieved]\n";
    else std::cerr<< "[unknown exception]\n";
  }

  return 0;
}
復制代碼

關于std::promise就是這些了,注意簡單介紹std::promise的能力以及如何使用,如果想更深入了解該類,建議直接閱讀一下源碼。

參考

https//www.apiref.com/cpp-zh/cpp/…

你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧

當前題目:C++多線程:std::promise-創新互聯
URL網址:http://vcdvsql.cn/article0/ddghio.html

成都網站建設公司_創新互聯,為您提供網站策劃、小程序開發網站改版電子商務、全網營銷推廣ChatGPT

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

網站優化排名