日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C++多线程:package_task异步调用任何目标执行操作

發布時間:2023/11/27 生活经验 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++多线程:package_task异步调用任何目标执行操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 描述
      • 函數成員及使用
      • 總結

我們上一篇描述關于C++多線程中的異步操作相關庫( asyncpromise),本節將分享c++標準庫中最后一個多線程異步操作庫 package_task的學習筆記。

描述

  • 頭文件 <future>

  • 聲明方式: template< class R, class ...Args > class packaged_task<R(Args...)>;

  • 簡介
    package_task標準類模版包裝了任何可調用的目標,其中包括函數,std::bind表達式,lamda表達式或者其他函數對象。并支持package_task對象調用者的異步調用。調用之后的返回值或者產生的異常能夠被存儲在能夠被std::future對象訪問的共享狀態中。

    綜上描述,我們很明顯能夠體會到該模版類提供的功能和promise類非常接近,但是promise類沒有辦法初始化所有可調用的對象,promise類僅提供共享狀態的多種訪問機制并提供線程之間變量的共享機制。

函數成員及使用

  • 構造函數
    packaged_task() noexcept;構造無任務且無共享狀態的package_task對象
    template <class F> explicit packaged_task( F&& f ) 構造擁有共享狀態和任務副本的 std::packaged_task 對象,
    packaged_task( const packaged_task& ) = delete;復制構造函數被刪除, std::packaged_task 僅可移動
    packaged_task( packaged_task&& rhs ) noexcept; rhs 之前所占有的共享狀態和任務構造 std::packaged_task ,令 rhs 留在無共享狀態且擁有被移動后的任務的狀態
    查看如下代碼:

    #include <future>
    #include <iostream>
    #include <thread>int fib(int n)
    {if (n < 3) return 1;else {std::cout << "fib  result " << (n-1)+(n-2) << std::endl;return (n-1) + (n-2);}
    }int main()
    {std::packaged_task<int(int)> fib_task(&fib); std::cout << "starting task\n";//此時已經將package_task調用對象的執行返回值轉交給future對象,所以后續//的線程執行由惰性賦值來觸發。即當future的對象的共享狀態嘗試獲取線程執行//結果的時候才進行線程執行,并返回結果。類似std::async的policy:std::launch::deferredauto result = fib_task.get_future(); std::thread t(std::move(fib_task), 40);std::cout << "waiting for task to finish...\n";std::cout << result.get() << '\n';std::cout << "task complete\n";t.join();
    }
    

    輸出如下:

    starting task
    waiting for task to finish...
    fib  result 77
    77
    task complete
    
  • 析構函數~packaged_task()
    拋棄共享狀態并銷毀存儲的任務對象,同 std::promise::~promise ,若在令共享狀態就緒前拋棄它,則存儲以 std::future_errc::broken_promise 為 error_code 的 std::future_error 異常

  • 賦值運算符
    packaged_task& operator=( const packaged_task& ) = delete
    復制賦值運算符被刪除, std::packaged_task 僅可移動

  • std::packaged_task<R(Args...)>::get_future返回與 *this 共享同一共享狀態的 future
    promise類一樣,get_future 只能對每個 packaged_task 調用一次
    get_future成員出現異常的情況如下:

    • 已通過調用 get_future 取得共享狀態。設置 error_category 為 future_already_retrieved
    • *this 無共享狀態。設置 error_category 為 no_state
  • std::packaged_task<R(Args...)>::make_ready_at_thread_exit成員函數
    以轉發的 args 為參數調用存儲的任務。任務返回值或任何拋出的異常被存儲于 *this 的共享狀態。

    僅在當前線程退出,并銷毀所有線程局域存儲期對象后,才令共享狀態就緒
    代碼如下

    #include <future>
    #include <iostream>
    #include <chrono>
    #include <thread>
    #include <functional>
    #include <utility>void worker(std::future<void>& output)
    {std::packaged_task<void(bool&)> my_task{ [](bool& done) { done=true; } };auto result = my_task.get_future();bool done = false;//根據打印已經可以看到,此時已經執行了package_task的線程內容//但是共享狀態到函數作用域結束之前并未就緒my_task.make_ready_at_thread_exit(done); // 立即執行任務std::cout << "worker: done = " << std::boolalpha << done << std::endl;auto status = result.wait_for(std::chrono::seconds(0));if (status == std::future_status::timeout)std::cout << "worker: result is not ready yet" << std::endl;output = std::move(result);
    }int main()
    {std::future<void> result;std::thread{worker, std::ref(result)}.join();//等到線程函數返回結果,且future對象就緒之后,可以看到打印狀態變為就緒auto status = result.wait_for(std::chrono::seconds(0));if (status == std::future_status::ready)std::cout << "main: result is ready" << std::endl;
    }
    

總結

綜上對package_task的描述,我們可以看到package_task模版類就像promise一樣可以被異步調用,并且將調用對象執行的結果封裝在future的共享狀態中,來讓調用者獲取。同時package_task的調用者獲取調用對象的執行結果過程就像async的惰性求值策略,當調用者想要獲取調用對象的執行結果時才開始執行調用對象。

package_task的優勢更多是它能夠初始化所有的可調用對象,并且支持對該調用對象的異步訪問機制。
promise更多的優勢是線程之間的變量的傳遞,同時返回future類的共享狀態。同時它也能夠支持多種共享狀態的訪問機制,惰性求值/立即執行。

所以C++多線程的幾個異步操作promiseasyncpackage_task都可以進行線程之間的異步操作,希望以此筆記在今后多線程編程中各持所需進行學習。

總結

以上是生活随笔為你收集整理的C++多线程:package_task异步调用任何目标执行操作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。