等到任何任务完成

时间:2017-05-06 11:58:28

标签: c++ multithreading task mutex condition-variable

我正在尝试编写一个简单的task类。它是std::future的包装器,它保持其状态(not_startedrunningcompleted),可以按需开始处理给定的作业,并且可以重复返回结果它的处理。

我还可以提供一些全局功能来处理这些任务。但我在编写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_variablestd::mutex来完成所有工作。有很多例子显示了这些东西的使用,但我根本不理解它,我没有找到解决这个特定问题的方法。

我猜我应该在std::condition_variable函数中创建cv(仅wait_any)。然后应该将cv(指针)注册到给定向量的所有任务。完成任何任务后(我可以处理完成任务的那一刻),它应该为此任务中注册的所有std::condition_variable::notify_one调用cv。这些通知的cv也应该从持有它们的所有任务中删除。

现在,我不知道如何使用mutex es。我可能需要阻止多次通知调用和许多其他问题。

任何帮助表示赞赏!

1 个答案:

答案 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