1. 程式人生 > 程式設計 >C++11 <future>中std::promise 介紹

C++11 <future>中std::promise 介紹

前面兩講《C++11 併發指南二(std::thread 詳解) 》,《C++11 併發指南三(std::mutex 詳解) 》分別介紹了 std::thread 和 std::mutex,相信讀者對 C++11 中的多執行緒程式設計有了一個最基本的認識,本文將介紹 C++11 標準中 <future> 標頭檔案裡面的類和相關函式。

<future> 標頭檔案中包含了以下幾個類和函式:

  • Providers 類:std::promise,std::package_task
  • Futures 類:std::future,shared_future.
  • Providers 函式:std::async()
  • 其他型別:std::future_error,std::future_errc,std::future_status,std::launch.

std::promise 類介紹

promise 物件可以儲存某一型別 T 的值,該值可被 future 物件讀取(可能在另外一個執行緒中),因此 promise 也提供了一種執行緒同步的手段。在 promise 物件構造時可以和一個共享狀態(通常是std::future)相關聯,並可以在相關聯的共享狀態(std::future)上儲存一個型別為 T 的值。

可以通過 get_future 來獲取與該 promise 物件相關聯的 future 物件,呼叫該函式之後,兩個物件共享相同的共享狀態(shared state)

  • promise 物件是非同步 Provider,它可以在某一時刻設定共享狀態的值。
  • future 物件可以非同步返回共享狀態的值,或者在必要的情況下阻塞呼叫者並等待共享狀態標誌變為 ready,然後才能獲取共享狀態的值。

下面以一個簡單的例子來說明上述關係

#include <iostream>    // std::cout
#include <functional>   // std::ref
#include <thread>     // std::thread
#include <future>     // std::promise,std::future

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

int main ()
{
  std::promise<int> prom; // 生成一個 std::promise<int> 物件.
  std::future<int> fut = prom.get_future(); // 和 future 關聯.
  std::thread t(print_int,std::ref(fut)); // 將 future 交給另外一個執行緒t.
  prom.set_value(10); // 設定共享狀態的值,此處和執行緒t保持同步.
  t.join();
  return 0;
}

std::promise 建構函式

default (1)
promise();
with allocator (2)
template <class Alloc> promise (allocator_arg_t aa,const Alloc& alloc);
copy [deleted] (3)
promise (const promise&) = delete;
move (4)
promise (promise&& x) noexcept;

  • 預設建構函式,初始化一個空的共享狀態。
  • 帶自定義記憶體分配器的建構函式,與預設建構函式類似,但是使用自定義分配器來分配共享狀態。
  • 拷貝建構函式,被禁用。
  • 移動建構函式。

另外,std::promise 的 operator= 沒有拷貝語義,即 std::promise 普通的賦值操作被禁用,operator= 只有 move 語義,所以 std::promise 物件是禁止拷貝的。

例子:

#include <iostream>    // std::cout
#include <thread>     // std::thread
#include <future>     // std::promise,std::future

std::promise<int> prom;

void print_global_promise () {
  std::future<int> fut = 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<int>();  // prom 被move賦值為一個新的 promise 物件.

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

 return 0;
}

std::promise::get_future 介紹

該函式返回一個與 promise 共享狀態相關聯的 future 。返回的 future 物件可以訪問由 promise 物件設定在共享狀態上的值或者某個異常物件。只能從 promise 共享狀態獲取一個 future 物件。在呼叫該函式之後,promise 物件通常會在某個時間點準備好(設定一個值或者一個異常物件),如果不設定值或者異常,promise 物件在析構時會自動地設定一個 future_error 異常(broken_promise)來設定其自身的準備狀態。上面的例子中已經提到了 get_future,此處不再重複。

std::promise::set_value 介紹

generic template (1)
void set_value (const T& val);
void set_value (T&& val);
specializations (2)
void promise<R&>::set_value (R& val);  // when T is a reference type (R&)
void promise<void>::set_value (void);  // when T is void

設定共享狀態的值,此後 promise 的共享狀態標誌變為 ready.

std::promise::set_exception 介紹
為 promise 設定異常,此後 promise 的共享狀態變標誌變為 ready,例子如下,執行緒1從終端接收一個整數,執行緒2將該整數打印出來,如果執行緒1接收一個非整數,則為 promise 設定一個異常(failbit) ,執行緒2 在std::future::get 是丟擲該異常。

#include <iostream>    // std::cin,std::cout,std::ios
#include <functional>   // std::ref
#include <thread>     // std::thread
#include <future>     // std::promise,std::future
#include <exception>   // std::exception,std::current_exception

void get_int(std::promise<int>& prom) {
  int x;
  std::cout << "Please,enter an integer value: ";
  std::cin.exceptions (std::ios::failbit);  // throw on failbit
  try {
    std::cin >> x;             // sets failbit if input is not int
    prom.set_value(x);
  } catch (std::exception&) {
    prom.set_exception(std::current_exception());
  }
}

void print_int(std::future<int>& fut) {
  try {
    int x = fut.get();
    std::cout << "value: " << x << '\n';
  } catch (std::exception& e) {
    std::cout << "[exception caught: " << e.what() << "]\n";
  }
}

int main ()
{
  std::promise<int> prom;
  std::future<int> fut = prom.get_future();

  std::thread th1(get_int,std::ref(prom));
  std::thread th2(print_int,std::ref(fut));

  th1.join();
  th2.join();
  return 0;
}

std::promise::set_value_at_thread_exit 介紹

設定共享狀態的值,但是不將共享狀態的標誌設定為 ready,當執行緒退出時該 promise 物件會自動設定為 ready。如果某個 std::future 物件與該 promise 物件的共享狀態相關聯,並且該 future 正在呼叫 get,則呼叫 get 的執行緒會被阻塞,當執行緒退出時,呼叫 future::get 的執行緒解除阻塞,同時 get 返回 set_value_at_thread_exit 所設定的值。注意,該函式已經設定了 promise 共享狀態的值,如果線上程結束之前有其他設定或者修改共享狀態的值的操作,則會丟擲 future_error( promise_already_satisfied )。

std::promise::swap 介紹

交換 promise 的共享狀態。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。