boost::future with continuations 的调度和生命周期

问题描述 投票:0回答:1

我对延续的期货的调度和生命周期有疑问。

如果您将来在

boost::future
上创建延续,然后函数返回而不阻塞延续本身的结果,它将运行延续。

如下所示:

#include <iostream>
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#include <boost/thread/future.hpp>

auto calculate_foo(int input) {

    auto a = boost::async([input]{
        std::cout << input << std::endl;
        return input * 2;
    });

    auto s = a.share();

    auto b = s.then([](auto t) {
        auto v = t.get();
        std::cout << v << std::endl;
        boost::this_thread::sleep_for(boost::chrono::milliseconds(v));
    });

    auto c = s.then([](auto t) {
      auto v = t.get();
      std::cout << v << std::endl;
      boost::this_thread::sleep_for(boost::chrono::milliseconds(v));

    });

    return s;
}

int main() {

    auto z = calculate_foo(1000);

    z.wait();

    return 0;
}

所以我有一个函数

calculate_foo
可以开始一些工作。然后我们创建 2 个延续
b
c
并故意在其中等待 sleep 以确保
calculate_foo
快速返回。

我原以为

b
c
仍然会被安排,因为我们返回了 parent future 但这似乎没有发生。

欢迎任何帮助来纠正我的理解。

c++ boost future
1个回答
0
投票

在您的代码中,您永远不会请求

b
c
期货的结果,因此,由于默认的 执行策略 此代码永远不会执行。

或更详细:

传递给

async()
的代码根据其参数指定的执行策略执行。对于
launch::async
策略,它在不同的线程中执行,而对于
launch::deferred
,它将在您请求未来的结果(或调用
wait()
)时内联执行。这同样适用于传递给
then()
的代码,因为它在内部只调用
async()
.

默认的执行策略是

launch::async | launch::deferred
,它让库决定使用哪个策略,通常选择延迟选项。因此,由于从未请求过结果,因此根本没有执行代码。

关于
boost
vs
std
的注意事项:

请记住,

then()
函数是实验性的,不符合 C++ 标准
std::future
。自从 C++11 发布以来,您应该更喜欢使用标准库设施而不是
boost
。在特性被纳入标准之前,Boost 通常充当“游乐场”。您可以使用
then()
实现
std::future
之类的功能,如下所示:

template<typename T, typename Func>
auto chain_to(std::launch policy, std::shared_future<T> f, Func&& second_func) {
    return std::async(policy, [f, second_func = std::forward<Func>(second_func)]() {
       return second_func(f);
    });
}

template<typename T, typename Func>
auto chain_to(std::shared_future<T> f, Func&& second_func) {
    return std::async([f, second_func = std::forward<Func>(second_func)]() {
       return second_func(f);
    });
}

// Use like:
auto b = chain_to(std::launch::async, my_first_shared_future, [](auto f) { ... });

这个 Godbolt 演示了使用

launch::async
你的代码将导致所有三个 lambda 被调用。

© www.soinside.com 2019 - 2024. All rights reserved.