首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >阻塞许多锁/期货/等,直到有任何锁准备好

阻塞许多锁/期货/等,直到有任何锁准备好
EN

Stack Overflow用户
提问于 2017-01-15 09:12:15
回答 2查看 833关注 0票数 12

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

代码语言:javascript
复制
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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-15 12:31:05

如果您有boost可用,那么它的线程处理能力远远超过标准库。

这将是在c++17之后的情况,从外观上看,甚至在c++20之后。

代码语言:javascript
复制
#include <future>
#include <vector>

#define BOOST_THREAD_VERSION 4
#include <boost/thread.hpp>


void wait_for_any(std::vector<boost::future<void>> & v)
{
    boost::wait_for_any(std::begin(v), std::end(v));
}
票数 7
EN

Stack Overflow用户

发布于 2017-01-15 10:11:27

备选案文1:

现在,这是不可能的,尽管,您可以通过编写自己的查找逻辑来解决这个问题。

代码语言:javascript
复制
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;
}

请注意,所有未来必须创建‘异步’标志,因为这将成为一个无限循环,如果他们是‘延迟’。

PS:如果您不希望它阻塞您的主线程,那么您可能希望在它自己的线程/将来执行它。

备选案文2:

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

代码语言:javascript
复制
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”结果的期货

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41659539

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档