我正在尝试编写一个简单的task
类。它是std::future
的包装器,它保持其状态(not_started
,running
,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;
}
}
}
我很感激被动等待任何完成。 std::this_thread::yield
函数可用,但我宁愿不使用它。如文档中所述:
此函数的确切行为取决于实现,尤其取决于正在使用的OS调度程序的机制以及系统的状态。
似乎我应该使用std::condition_variable
和std::mutex
来完成所有工作。有很多例子显示了这些东西的使用,但我根本不理解它,我没有找到解决这个特定问题的方法。
我猜我应该在std::condition_variable
函数中创建cv
(仅wait_any
)。然后应该将cv
(指针)注册到给定向量的所有任务。完成任何任务后(我可以处理完成任务的那一刻),它应该为此任务中注册的所有std::condition_variable::notify_one
调用cv
。这些通知的cv
也应该从持有它们的所有任务中删除。
现在,我不知道如何使用mutex
es。我可能需要阻止多次通知调用和许多其他问题。
任何帮助表示赞赏!
答案 0 :(得分: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