今天來記錄個覺得應該很有用的東西
就是promise,future和async
以下是幾個我參考的網頁:
https://wizardforcel.gitbooks.io/cpp-11-faq/content/70.html
https://kheresy.wordpress.com/2016/03/14/async-and-future-in-c11/
先從future和promise開始看起好了
future從字面看是未來的意思,也就是代表:現在沒辦法馬上獲得結果,也許之後才會得到結果
promise字面上是承諾的意思,也就是會給予一個值
以下來看一個簡單的範例:
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;
}
其實裡面註解就解釋得很清楚了
我們可以綁定future到promise裡面,然後把future設定到另一個thread中
當main thread需要傳送資料給child thread時,可以用promise去設定那個值
而在child thread裡面可以用future去get那個值
進而達到multithread間溝通和同步的效果
其實從上面的例子看起來,future有點像是thread之間shared的狀態
而promise就是設定那個狀態的一個接口
所以說我們如果要實作一個可以從外部中斷的task,我們就可以利用這個機制來實作
比如說在一個物件裡面,包含一個promise和一個future:
class Stoppable
{
std::promise<void> exitSignal;
std::future<void> futureObj;
public:
Stoppable() : futureObj(exitSignal.get_future())
{
std::cout << "Initialize Stoppable task" << std::endl;
}
virtual ~Stoppable()
{
std::cout << "disconstruct the task" << std::endl;
}
Stoppable(Stoppable && obj) : exitSignal(std::move(obj.exitSignal)), futureObj(std::move(obj.futureObj))
{
std::cout << "Move Constructor is called" << std::endl;
}
Stoppable & operator=(Stoppable && obj)
{
std::cout << "Move Assignment is called" << std::endl;
exitSignal = std::move(obj.exitSignal);
futureObj = std::move(obj.futureObj);
return *this;
}
void operator()()
{
run();
}
// check if this task is requested to stop.
bool stopRequested()
{
while (futureObj.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout)
{
// futureObj has not received stop signal, so this task is not requested to stop.
return false;
}
return true;
}
// request this task to stop by setting value to promise.
void stop()
{
exitSignal.set_value();
}
private:
virtual void run() = 0;
};
當呼叫stop()的時候便會去設定promise的值,在run()的實作中就可以去檢查future的值,利用這個特性去達到停止的效果,比如說像這樣:
void counter::run()
{
int count = 0;
while (stopRequested() == false)
{
std::cout << "count = " << count << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
++count;
}
std::cout << "counter end" << std::endl;
}
上面是一個counter實作的例子,這個counter會一直數到使用者呼叫stop()為止
如果簡單執行的話,就是開一個thread來執行:
counter c();
std::thread th([&]() {
c.run();
});
當然也可以在counter裡面有一個thread的member然後用這個thread來執行,
抑或是在Stoppable裡面就有一個thread的member來讓子類繼承,我想都是可以的
async的話使用上就比較單純,如果是簡單使用的話建議用async就行了
和future結合使用也很方便,以下是一個範例:
int Compute( int iIn)
{
std::this_thread::sleep_for(std::chrono::seconds(iIn));
return iIn;
}
int main(int argc, char** argv)
{
auto tpStart = std::chrono::high_resolution_clock::now();
std::future<int> fuRes1 = std::async(std::launch::async, Compute, 1),
fuRes2 = std::async(std::launch::async, Compute, 2);
int iResult = fuRes1.get() + fuRes2.get();
auto duTime = std::chrono::high_resolution_clock::now() – tpStart;
std::cout << "Result is " << iResult << ", use "
<< std::chrono::duration_cast<std::chrono::milliseconds>(duTime).count()
<< "ms" << std::endl;
}
async的特點就是它會有個回傳值,而可以使用future去接async的回傳值
使用上就用future.get()去得到回傳的值,而如果還沒拿到回傳值的話就會停在那邊等待
以這個例子來說,主程式會卡在iResult那邊,等到兩個值都算完之後可以加起來才會繼續
然後這邊還有計算一下執行的時間,也可以參考一下用法
另外上述做法也可以用thread來實現,大該就是要傳參數進去讓thread可以把值存到參數中,比較麻煩一點
具體的做法可以參考: https://kheresy.wordpress.com/2016/03/14/async-and-future-in-c11/
大概就這樣啦,稍微知道一下用法而已
其實這樣就可以便很多花招了XD
留言列表