You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Seastar中when_all等待多future异常及编译相关疑问

Seastar Future等待问题解答

问题背景

以下是相关代码:

#include <seastar/core/app-template.hh>
#include <seastar/core/coroutine.hh>
#include <seastar/core/sleep.hh>
#include <seastar/core/when_all.hh>

/*Here I want all the futures to execute*/
seastar::future<> all_futures()
{
    seastar::sleep(2s).then([]{std::cout << "2s\n";});
    seastar::sleep(1s).then([]{std::cout << "1s\n";});
    return seastar::sleep(3s).then([]{std::cout << "3s\n";});//CHANGE HERE TO VALUE < 2s
}

seastar::future<int> get_int()
{
    std::cout << "Entering winter sleep\n";
    return seastar::sleep(5s).then([]{return 2;}); //CHANGE HERE TO VALUE < 3s
}

seastar::future<> f_sleeping() {
    std::cout << "Sleeping... " << std::flush;
    using namespace std::chrono_literals;
//Here I want to wait for all the futures and only exit after all futures finished
    return when_all(all_futures(),get_int().then([](const int val){std::cout << "got: " << val << '\n'; })).discard_result();
}

int main(int argc, char** argv) {
    app_template app;

    return app.run(argc, argv, [&app] {
        
        return f_sleeping();
    });
}

原代码运行时符合预期,但修改标记为//CHANGE HERE TO VALUE行的sleep时长(分别改为小于2s和小于3s)后,部分future未被等待。

错误信息翻译

错误:无法将‘seastar::when_all(FutOrFuncs&& ...) [with FutOrFuncs = {seastar::future<>, seastar::future<>, seastar::future<>}]((* & std::move(seastar::future<>&>(one))), (* & std::move(seastar::future<>&>(three))))’从‘future<std::tuple<seastar::future, seastar::future<>, seastar::future<> >>’转换为‘future<>’
172 | return when_all(std::move(two), std::move(one), std::move(three));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| future<std::tuple<seastar::future, seastar::future<>, seastar::future<> >>


问题解答

1. 如何正确等待任意数量的future?

要正确等待所有future,核心是不能丢弃任何需要执行的future,必须将所有待执行的future收集并通过when_all等待:

  • 对于固定数量的future,直接将所有future作为参数传入when_all,最后调用discard_result()将结果转换为future<>:
seastar::future<> all_futures()
{
    auto f1 = seastar::sleep(2s).then([]{std::cout << "2s\n";});
    auto f2 = seastar::sleep(1s).then([]{std::cout << "1s\n";});
    auto f3 = seastar::sleep(3s).then([]{std::cout << "3s\n";});
    return seastar::when_all(std::move(f1), std::move(f2), std::move(f3)).discard_result();
}
  • 对于任意数量(动态)的future,可将其存入容器(如std::vector<seastar::future<>>),使用when_all的迭代器版本:
seastar::future<> wait_dynamic_futures()
{
    std::vector<seastar::future<>> futures;
    futures.emplace_back(seastar::sleep(1s).then([]{std::cout << "1s\n";}));
    futures.emplace_back(seastar::sleep(2s).then([]{std::cout << "2s\n";}));
    futures.emplace_back(seastar::sleep(3s).then([]{std::cout << "3s\n";}));
    return seastar::when_all(futures.begin(), futures.end()).discard_result();
}

关键注意点:所有需要执行的future必须被变量持有,否则Seastar会自动取消未被引用的future,导致对应的回调不会执行。

2. 该异常是Seastar库的bug,还是C++编译阶段无法检测此类问题?

这既不是Seastar的bug,也不是编译阶段无法检测的问题,而是开发者的逻辑错误:

  • Seastar的future设计规则是:如果一个future没有被任何对象持有或等待,会被自动取消,避免资源泄漏。原代码中all_futures函数里的前两个sleep future创建后直接被丢弃,没有被等待,当第三个sleep提前完成时,函数返回,前两个future被销毁并取消,因此不会执行回调。
  • C++编译阶段无法检测这类问题,因为编译器无法跟踪运行时对象的引用关系,无法判断开发者是否打算等待某个future。

3. 查阅when_all声明可知其接受迭代器对,但代码未传入迭代器却能编译运行且无警告,原因是什么?

Seastar的when_all提供了多个重载版本:

  • 一个版本接受迭代器对,用于等待容器中的所有future;
  • 另一个版本接受可变参数(FutOrFuncs&&...),可以直接传入任意数量的future或可调用对象,返回一个future<std::tuple<...>>,其中tuple的元素对应每个输入future的结果类型。

代码中使用的是可变参数重载版本,只要传入的是合法的future对象,就会匹配该重载,因此可以正常编译运行,不会出现警告或错误。


内容的提问来源于stack exchange,提问作者Deborah C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 01:10:24