2017-05-06 76 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