阻止许多锁/期货/等。直到任何准备好

时间:2017-01-15 09:12:16

标签: c++ multithreading c++11

是否有可能阻止一组锁定/期货/任何可阻止的实体,直到其中任何一个准备就绪?我们的想法是:

std::vector<std::future<T>> futures = ...;
auto ready_future = wait_until_an_element_is_ready(futures);
process(ready_future.get());

我记得像libevent,libev和libuv这样的库具有IO任务的这种能力。但我不知道这些是否可以用于锁/期货。

我想到的一种方法就是让期货在完成后调用处理程序,但同时将处理程序比较并交换为null,以便其他期货不能调用它。然而,这需要协调期货,因此无法对锁进行。

更新: C ++ 2x似乎有proposal

2 个答案:

答案 0 :(得分:6)

如果您有可用的增强功能,其线程功能远远超过标准库。

这将是在c ++ 17之后的情况,以及事物的外观,即使在c ++ 20之后。

{{1}}

答案 1 :(得分:0)

备选方案1:

现在,这是不可能的,你可以通过编写自己的查找逻辑来解决它。

template<typename Iterator>
Iterator find_first_ready_future(Iterator begin, Iterator end)
{
    return std::find_if(begin, end, [](auto &future) { return future.wait_for(0s) == std::future_status::ready; }
}

template<typename T>
std::future<T> wait_until_an_element_is_ready(std::vector<std::future<T>> &vector)
{
    assert(!vector.empty());
    auto iterator = vector.end();
    do
    {
        // force switch of threads (if you don't want a busy loop, you might want to sleep this thread)
        // If reaction speed is very important, you might want to skip this first yield/sleep in the first iteration.
        std::this_thread::yield();

        iterator = find_first_ready_future(vector.begin(), vector.end());
    } while (iterator == vector.cend());
    auto result = std::move(*iterator);
    vector.erase(iterator); // Remove the ready future to prepare for the next call. (You ain't allowed to call .get() twice)
    return result;
}

请注意,所有期货都必须使用'async'标志创建,因为如果'延迟',这将成为无限循环。

PS:如果你不想让你的主线程阻塞,你可能想在自己的线程/未来执行它。

备选方案2:

另一种选择是包装你的期货来执行任务。这有点类似于future.then提案:

template<typename T>
std::vector<std::future<void>> executeOnComplete(std::vector<std::future<T>> &&v)
{
    std::vector<std::future<void>> result;
    result.reserve(v.size());
    for (auto &f : v)
       result.emplace(std::async(std::launch::async,
                [f = std::move(f)] { process(f.get()); }));
    return result;
}

此替代方案为每个未来创建一个新线程,并将阻止它直到原始未来准备就绪。它带来了创建太多线程的风险。

PS:有了一些花哨的result_of模板逻辑,你甚至可以创建返回`process

结果的期货