2017-05-06 73 views
0

我正在嘗試編寫一個簡單的task類。它是一個圍繞std::future的包裝,它保持其狀態(not_startedrunning,completed),可以根據需要開始處理給定作業,並且可以重複返回其處理結果。等到任何任務完成

我也可以提供一些全局函數來處理這些任務。但是我有點卡在size_t wait_any(std::vector<task<T>>& tasks)函數中。這個函數被賦予一個任務向量,並且應該返回第一個完成任務的索引。如果在開始時完成了更多任務,則必須返回其中一個(但這不是問題)。

採用主動等待一個簡單的實現如下:

template <typename T> 
size_t wait_any(std::vector<task<T>>& tasks) { 

    if (tasks.size() == 0) throw std::exception("Waiting for empty vector of tasks!"); 

    for (auto i = tasks.begin(); i != tasks.end(); ++i) { 
     (*i).try_start(); 
    } 

    while (true) { 
     for (size_t i = 0; i != tasks.size(); ++i) { 
      if (tasks[i].is_completed()) return i; 
     } 
    } 
} 

我將不勝感激被動等待任何completition。 A std::this_thread::yield功能可用,但我寧願不使用它。正如文檔中提到的:

該函數的確切行爲取決於實現,特別是關於正在使用的OS調度器的機制和系統狀態。

看來,我應該使用std::condition_variablestd::mutex讓整個事情的工作。有很多例子顯示了這些東西的用法,但是我根本不理解它,而且我還沒有找到解決這個特定問題的方法。

我想我應該在wait_any函數中創建一個std::condition_variable(只需cv)。然後這個cv(指針)應該被註冊到來自給定矢量的所有任務。一旦任何任務完成(我可以處理任務完成的時刻),它應該在本任務中註冊所有cv的電話std::condition_variable::notify_one。這些通知cv也應從所有持有它們的任務中移除。現在,我不知道如何使用mutex es。我可能需要防止多次通知和其他許多問題。

任何幫助表示讚賞!

+0

這個例子可以幫助:http://stackoverflow.com/documentation/c%2b%2b/699/threading/13552/using-condition -variables#t = 201705061205000751576 – didiz

+0

因爲您正在使用所有CPU,所以無法完成等待任務完成。 – stark

回答

0

我在想,既然你只需要一個通知,你可以使用std::call_once來設置你需要的task_id。

一個天真的方式去了解這將是:

#include <iostream> 
#include <vector> 
#include <thread> 

    std::once_flag lala; 
    std::atomic_int winner(-1); 

    void silly_task(int task_id) 
    { 
     //do nothing 
     std::call_once (lala, [&]() 
     { 
      std::cout << "thread " << task_id << " wins" << std::endl; 
      winner = task_id; 
     }); 
    } 

    int main(){ 

     std::vector<std::thread> vt; 
     for (int i=0; i < 10 ; i ++) 
     { 
      vt.push_back(std::thread(&silly_task, i)); 

     } 

     while (winner == -1) 
     { 
      std::this_thread::sleep_for(std::chrono::seconds(1)); 
     } 
     for (int i=0; i < 10 ; i ++) 
     { 
      vt[i].join(); 

     } 

     return 0; 
    } // end main