亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

c++11封裝thread庫的方法示例

發布時間:2020-10-02 09:11:39 來源:腳本之家 閱讀:153 作者:chaozh.com 欄目:編程語言

前言

c++11在語言層面上提供了對thread的支持,由于不同的平臺提供了不同線程API,在語言層面提供了對thread的支持可以大大的減小代碼移植的工作量。

本文將給大家詳細介紹關于c++11封裝thread庫的相關內容,下面話不多說了,來一起看看詳細的介紹吧

基本接口要求

要求std::thread的構造函數

template< class Function, class... Args > 
explicit thread( Function&& f, Args&&... args );

但是OS的庫函數定義為:

error_code create_thread((void_or_error_code(*entry)(void *), void *data);

主要是接口中的entry,本身使用void*根本沒帶類型信息,難點在于要做到模板暴露出類型從而可以通用化

void_or_error_code entry_point(void *arbitrary_data);

第一個問題:把f和args統統打包在一起做成一個void *結構

我們得從void* 中獲取函數指針和參數指針,首先來個結構體定義真實指針類型

struct thread_data_base
{
 virtual ~thread_data_base(){}
 virtual void run()=0;
};

需要一個tuple,用于保存f和args,這樣我們就可以通過將void *data cast成thread_data_base *,然后調用其中的虛函數run來實際調用f(args…)

std::tuple<typename std::decay<F>::type, typename std::decay<ArgTypes>::type...> fp;

而entry函數實現效果大致如下,將結構體包裝在該函數里面

void_or_error_code thread_entry(void *data) {
 std::unique_ptr<thread_data_base> p((thread_data_base *)data);
 p->run();
 // return result of p->run() if error code is required
}

第二個問題:定義一個template,以適配不同類型的f和args

template<typename F, class... ArgTypes>
class thread_data : public thread_data_base
{
public:
 thread_data(F&& f_, ArgTypes&&... args_): fp(std::forward<F>(f_), std::forward<ArgTypes>(args_)...) {}
private:
 std::tuple<typename std::decay<F>::type, typename std::decay<ArgTypes>::type...> fp;
}

在這個template里有一個data member正是那個關鍵的tuple,其類型需要使用traits進行類型推理出來

第三個問題:把任意的f和args包裝成一個thread_data_base *

定義創建函數可以將任意f和arg來創建一個void*結構體,用來被entry函數調用

template<typename F, class... ArgTypes>
inline thread_data_base *make_thread_data(F&& f, ArgTypes&&... args)
{
 return new thread_data<typename std::remove_reference<F>::type, ArgTypes...>(std::forward<F>(f),
                   std::forward<ArgTypes>(args)...); // 啥時候釋放?
}

第四個問題:如何處理Args…

難點在于如何通過一個f和args組成的tuple調用f(args…),使用get需要傳入一個編譯期常量

tp.get<0>()(tp.get<1>(), tp.get<2>(), tp.get<3>());

為了方便,我們想把數列當前項直接放在參數列表里,要不然還需要在內部找到數列的最后一項

template <std::size_t Ep, std::size_t Sp>
struct make_tuple_indices {...};

為了生成數列[Sp, Ep),我們要做的就是從Sp開始,遞歸的在已有數列后面加一項,直到滿足條件(Sp==Ep),下面就是最后定義的泛化,遞歸,終止條件

template <std::size_t Sp, class IntTuple, std::size_t Ep> struct make_indices_imp;

template <std::size_t Sp, std::size_t... Indices, std::size_t Ep>
struct make_indices_imp<Sp, tuple_indices<Indices...>, Ep>
{ typedef typename make_indices_imp<Sp+1, tuple_indices<Indices..., Sp>, Ep>::type type; };

template <std::size_t Ep, std::size_t... Indices>
struct make_indices_imp<Ep, tuple_indices<Indices...>, Ep>
{ typedef tuple_indices<Indices...> type; };

template <std::size_t Ep, std::size_t Sp=0>
struct make_tuple_indices {
 typedef typename make_indices_imp<Sp, tuple_indices<>, Ep>::type type;
};

已經有了run,之所以需要再定義一個run2,Indices是一個template type,只能用一個template function接收,所以我們需要把run和run2拆開,run作為繼承下來的虛函數做入口,run2接收Indices并用之前提到的方法調用f(args…)。

實際上thread_data_base接口就是實現了一個簡化版的std::bind

靜態檢查工具:Clang thread safety annotations,添加安全注解:通過代碼注解告訴編譯器哪些成員變量和成員函數是受哪個 mutex 保護,防止遺漏線程安全的假設。用 GUARDED_BY 表明哪個成員變量是被哪個 mutex 保護的

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

大英县| 沙田区| 泗水县| 兰州市| 平湖市| 泰顺县| 略阳县| 色达县| 双流县| 新野县| 榆社县| 台山市| 额尔古纳市| 天水市| 九寨沟县| 梁山县| 通渭县| 阜平县| 铜陵市| 巧家县| 化德县| 鄢陵县| 靖西县| 宁南县| 平果县| 安乡县| 类乌齐县| 延寿县| 满洲里市| 涞源县| 木里| 惠东县| 黄浦区| 东丽区| 普安县| 德兴市| 运城市| 湛江市| 马公市| 抚州市| 会宁县|