1717
1818#include < seastar/core/abort_source.hh>
1919#include < seastar/core/condition-variable.hh>
20+ #include < seastar/core/coroutine.hh>
2021#include < seastar/core/future-util.hh>
2122#include < seastar/core/future.hh>
2223#include < seastar/core/gate.hh>
@@ -352,17 +353,35 @@ inline void spawn_with_gate(seastar::gate& g, Func&& func) noexcept {
352353template <class Func >
353354inline void
354355repeat_until_gate_closed (seastar::gate& gate, Func&& func) noexcept {
355- spawn_with_gate (gate, [&gate, func = std::forward<Func>(func)]() mutable {
356- return ss::do_until (
357- [&gate] { return gate.is_closed (); },
358- [func = std::forward<Func>(func)]() mutable {
359- return ss::futurize_invoke (func).handle_exception (
360- [](const std::exception_ptr&) {
361- // A generic catch all to avoid exceptional futures.
362- // The input func may include it's own exception handling.
363- });
364- });
365- });
356+ repeat_until_gate_closed (
357+ gate, std::forward<Func>(func), [](const std::exception_ptr&) {});
358+ }
359+
360+ // / \brief Repeats the passed func in a detached fiber until the gate is closed,
361+ // / invoking exception_handler on any exception.
362+ // /
363+ // / \param gate Gate object to use.
364+ // / \param func function to invoke.
365+ // / \param exception_handler called with any exception thrown by func.
366+ template <class Func , class ExceptionHandler >
367+ inline void repeat_until_gate_closed (
368+ seastar::gate& gate,
369+ Func&& func,
370+ ExceptionHandler&& exception_handler) noexcept {
371+ spawn_with_gate (
372+ gate,
373+ [&gate,
374+ func = std::forward<Func>(func),
375+ exception_handler = std::forward<ExceptionHandler>(exception_handler)](
376+ this auto ) -> seastar::future<> {
377+ while (!gate.is_closed ()) {
378+ try {
379+ co_await seastar::futurize_invoke (func);
380+ } catch (...) {
381+ exception_handler (std::current_exception ());
382+ }
383+ }
384+ });
366385}
367386
368387// / \brief Repeats the passed func in a detached fiber until the gate is closed
@@ -374,17 +393,37 @@ repeat_until_gate_closed(seastar::gate& gate, Func&& func) noexcept {
374393template <class Func >
375394inline void repeat_until_gate_closed_or_aborted (
376395 ss::gate& gate, ss::abort_source& as, Func&& func) noexcept {
396+ repeat_until_gate_closed_or_aborted (
397+ gate, as, std::forward<Func>(func), [](const std::exception_ptr&) {});
398+ }
399+
400+ // / \brief Repeats the passed func in a detached fiber until the gate is closed
401+ // / or abort is triggered, invoking exception_handler on any exception.
402+ // /
403+ // / \param gate Gate object to use.
404+ // / \param as Abort source to use.
405+ // / \param func function to invoke.
406+ // / \param exception_handler called with any exception thrown by func.
407+ template <class Func , class ExceptionHandler >
408+ inline void repeat_until_gate_closed_or_aborted (
409+ ss::gate& gate,
410+ ss::abort_source& as,
411+ Func&& func,
412+ ExceptionHandler&& exception_handler) noexcept {
377413 spawn_with_gate (
378- gate, [&gate, &as, func = std::forward<Func>(func)]() mutable {
379- return ss::do_until (
380- [&gate, &as] { return as.abort_requested () || gate.is_closed (); },
381- [func = std::forward<Func>(func)]() mutable {
382- return ss::futurize_invoke (func).handle_exception (
383- [](const std::exception_ptr&) {
384- // A generic catch all to avoid exceptional futures.
385- // The input func may include it's own exception handling.
386- });
387- });
414+ gate,
415+ [&gate,
416+ &as,
417+ func = std::forward<Func>(func),
418+ exception_handler = std::forward<ExceptionHandler>(exception_handler)](
419+ this auto ) -> seastar::future<> {
420+ while (!as.abort_requested () && !gate.is_closed ()) {
421+ try {
422+ co_await seastar::futurize_invoke (func);
423+ } catch (...) {
424+ exception_handler (std::current_exception ());
425+ }
426+ }
388427 });
389428}
390429
0 commit comments