2015-06-20 101 views
0

有人可以解釋在下面的lambda函數中創建線程的位置嗎? 使用什麼技術? 有人可以推薦一個參考來理解語義嗎?使用lambda表達式構建線程

我現在張貼的全碼:

class ThreadPool { 
public: 
    ThreadPool(size_t); 
    template<class F, class... Args> 
    auto enqueue(F&& f, Args&&... args) 
     ->std::future<typename std::result_of<F(Args...)>::type>; 
    ~ThreadPool(); 
private: 
    // need to keep track of threads so we can join them 
    std::vector<std::thread> workers_m; 
    // the task queue 
    std::queue< std::function<void()> > tasks_m; 

    // synchronization 
    std::mutex queue_mutex_m; 
    std::condition_variable condition_m; 
    bool stop_m; 
}; 

// the constructor just launches some amount of workers 
inline ThreadPool::ThreadPool(size_t threads) 
    : stop_m(false) 
{ 
    std::thread::id id = std::this_thread::get_id(); 
    for (size_t i = 0; i < threads; ++i) 
    { 
     workers_m.emplace_back(
      [this] 
     { 
      for (;;) 
      { 
       std::function<void()> task; 
       { 
        std::unique_lock<std::mutex> lock(this- >queue_mutex_m); 
        std::thread::id id1 = std::this_thread::get_id(); 
        this->condition_m.wait(lock, [this]{ return this->stop_m || !this->tasks_m.empty(); }); 
        std::thread::id id = std::this_thread::get_id(); 
        if (this->stop_m && this->tasks_m.empty()) 
         return; 
        task = std::move(this->tasks_m.front()); 
        this->tasks_m.pop(); 
       } 
       task(); 
      } 
     } 
     ); 
    } 
} 
+0

您沒有在任何地方創建線程。 –

+0

感謝T.C.,我現在添加了完整的代碼 – user2286810

+0

'emplace_back'函數被賦予了一個lambda,它在'workers_m'向量上構造了一個'std :: thread'。 – Alejandro

回答

0

ThreadPool的構造函數使用的std::vectoremplace_back功能構建std::threadworkers_m變量的後面。 emplace_backpush_back不同之處在於它通過轉發傳遞給元素類型構造函數的參數(std::thread)直接構造元素類型。另一方面,另一方面,要求左值或臨時元素類型,然後將其適當地複製或移動到矢量的後面。

ThreadPool的構造函數將在for循環中執行此操作,以創建適當數量的工作線程,如構造函數參數(threads)所指定。 std::threads constructors之一需要一個可調用的和任意數量的參數,並將在相應的線程上運行該函數。在這種情況下,傳入的lambda被用來構造一個只要需要就運行的線程(由for(;;)給出),獲取一個互斥體以授予對任務隊列的獨佔訪問權,並使用一個條件變量來等待要麼設置停止標誌,要麼直到隊列中有可用的東西。

一旦通知條件變量並且兩個條件中的一個爲真,該線程就可以繼續。然而,這兩個條件是真不知道,因此對於

if (this->stop_m && this->tasks_m.empty()) 
        return; 

這似乎有點瑕疵的,雖然檢查,因爲如果stop_m設置工作線程應該停止處理任務,即使隊列仍包含要做的任務。但是這種檢查只會觸發這兩種情況都是事實。

如果上面的檢查是錯誤的,線程std::move的任務就是從隊列中執行pop() s,然後釋放由鎖的析構函數決定的由unique_lock保存的互斥鎖。線程然後通過調用它來執行任務。由於for(;;)循環,此過程重複執行

+0

謝謝亞歷杭德羅,你的回答很棒 – user2286810

+0

太棒了!我很高興我能幫忙=) – Alejandro