keep_doing与repeat区别

1 keep_doing

在github中提到seastar官方教程

To repeatedly accept new connections, we use the keep_doing() loop idiom. keep_doing() runs its lambda parameter over and over, starting the next iteration as soon as the future returned by the previous iteration completes. The iterations only stop if an exception is encountered. The future returned by keep_doing() itself completes only when the iteration stops (i.e., only on exception).

为了重复接收新的连接,可以使用keep_doing原语,keep_doing的原型如下:

template
GCC6_CONCEPT( requires seastar::ApplyReturns> )
inline
future<> keep_doing(AsyncAction action) {
    return repeat([action = std::move(action)] () mutable {
        return action().then([] {
            return stop_iteration::no;
        });
    });
}

keep_doing会不断执行异步函数action,当前一次执行完成便开始执行下一次,遍历执行只有在异常发生时下才会终止,因此keep_doing函数返回的future只有在action执行时发生异常才会完成。
从keep_doing的实现来看,就没有机会return stop_iteration::yes

2 repeat

repeat的函数原型:

template
GCC6_CONCEPT( requires seastar::ApplyReturns || seastar::ApplyReturns> )
inline
future<> repeat(AsyncAction action) {
    using futurator = futurize>;
    static_assert(std::is_same, typename futurator::type>::value, "bad AsyncAction signature");
    using futurized_action_type = typename internal::futurized_action::type;
    auto futurized_action = futurized_action_type(std::move(action));
    try {
        do {
            // Do not type-erase here in case this is a short repeat()
            auto f = futurized_action();

            if (!f.available()) {
              return [&] () noexcept {
                memory::disable_failure_guard dfg;
                auto repeater = std::make_unique>(std::move(futurized_action));
                auto ret = repeater->get_future();
                internal::set_callback(f, std::move(repeater));
                return ret;
              }();
            }

            if (f.get0() == stop_iteration::yes) {
                return make_ready_future<>();
            }
        } while (!need_preempt());

        auto repeater = std::make_unique>(stop_iteration::no, std::move(futurized_action));
        auto ret = repeater->get_future();
        schedule(std::move(repeater));
        return ret;
    } catch (...) {
        return make_exception_future(std::current_exception());
    }
}

从代码来看f.get0 == stop_iteration::yes,也就是action这个lamada函数如果返回值是stop_iteration,repeat就会返回,同时抛出异常时也会返回。

3 总结

keep_doing是对repeat的一次封装,忽略了stop_iteration::yes这个返回值,只有在抛出异常时才会退出,而repeat在lambda函数抛出异常或者返回stop_iteration::yes都会退出。
另外keep_doingrepeat虽然官网都有提到,但是在基于seastar的开源项目scylladb里使用的都是repeat,很少使用keep_doing,但是在一些example里都是使用keep_doing居多。
后续继续补充源码分析~

你可能感兴趣的:(keep_doing与repeat区别)