From: Pavel Emelyanov <
xe...@scylladb.com>
Committer: Pavel Emelyanov <
xe...@scylladb.com>
Branch: master
reactor: Move reactor::complete_timers() to timer_set
The method wants to log timer callback error, but its't not easy to put
logger into timer-set low-level header, so declare it as external helper
from reactor.cc
Signed-off-by: Pavel Emelyanov <
xe...@scylladb.com>
---
diff --git a/include/seastar/core/reactor.hh b/include/seastar/core/reactor.hh
--- a/include/seastar/core/reactor.hh
+++ b/include/seastar/core/reactor.hh
@@ -355,8 +355,6 @@ private:
void expire_manual_timers() noexcept;
void start_aio_eventfd_loop();
void stop_aio_eventfd_loop();
- template <typename T, typename E, typename EnableFunc>
- void complete_timers(T&, E&, EnableFunc&& enable_fn) noexcept(noexcept(enable_fn()));
/**
* Returns TRUE if all pollers allow blocking.
diff --git a/include/seastar/core/timer-set.hh b/include/seastar/core/timer-set.hh
--- a/include/seastar/core/timer-set.hh
+++ b/include/seastar/core/timer-set.hh
@@ -23,6 +23,10 @@
namespace seastar {
+namespace internal {
+void log_timer_callback_exception(std::exception_ptr) noexcept;
+}
+
/**
* A data structure designed for holding and expiring timers. It's
* optimized for timer non-delivery by deferring sorting cost until
@@ -85,6 +89,7 @@ private:
{
return bitsets::get_last_set(_non_empty_buckets);
}
+
public:
timer_set() noexcept
: _last(0)
@@ -209,6 +214,36 @@ public:
return exp;
}
+ template <typename EnableFunc>
+ void complete(timer_list_t& expired_timers, EnableFunc&& enable_fn) noexcept(noexcept(enable_fn())) {
+ expired_timers = expire(this->now());
+ for (auto& t : expired_timers) {
+ t._expired = true;
+ }
+ const auto prev_sg = current_scheduling_group();
+ while (!expired_timers.empty()) {
+ auto t = &*expired_timers.begin();
+ expired_timers.pop_front();
+ t->_queued = false;
+ if (t->_armed) {
+ t->_armed = false;
+ if (t->_period) {
+ t->readd_periodic();
+ }
+ try {
+ *internal::current_scheduling_group_ptr() = t->_sg;
+ t->_callback();
+ } catch (...) {
+ internal::log_timer_callback_exception(std::current_exception());
+ }
+ }
+ }
+ // complete_timers() can be called from the context of run_tasks()
+ // as well so we need to restore the previous scheduling group (set by run_tasks()).
+ *internal::current_scheduling_group_ptr() = prev_sg;
+ enable_fn();
+ }
+
/**
* Returns a time point at which expire() should be called
* in order to ensure timers are expired in a timely manner.
diff --git a/src/core/reactor.cc b/src/core/reactor.cc
--- a/src/core/reactor.cc
+++ b/src/core/reactor.cc
@@ -1524,36 +1524,6 @@ reactor::block_notifier(int) {
engine()._cpu_stall_detector->on_signal();
}
-template <typename T, typename E, typename EnableFunc>
-void reactor::complete_timers(T& timers, E& expired_timers, EnableFunc&& enable_fn) noexcept(noexcept(enable_fn())) {
- expired_timers = timers.expire(timers.now());
- for (auto& t : expired_timers) {
- t._expired = true;
- }
- const auto prev_sg = current_scheduling_group();
- while (!expired_timers.empty()) {
- auto t = &*expired_timers.begin();
- expired_timers.pop_front();
- t->_queued = false;
- if (t->_armed) {
- t->_armed = false;
- if (t->_period) {
- t->readd_periodic();
- }
- try {
- *internal::current_scheduling_group_ptr() = t->_sg;
- t->_callback();
- } catch (...) {
- seastar_logger.error("Timer callback failed: {}", std::current_exception());
- }
- }
- }
- // complete_timers() can be called from the context of run_tasks()
- // as well so we need to restore the previous scheduling group (set by run_tasks()).
- *internal::current_scheduling_group_ptr() = prev_sg;
- enable_fn();
-}
-
#ifdef HAVE_OSV
void reactor::timer_thread_func() {
sched::timer tmr(*sched::thread::current());
@@ -1566,7 +1536,7 @@ void reactor::timer_thread_func() {
_timer_due = 0;
_engine_thread->unsafe_stop();
_pending_tasks.push_front(make_task(default_scheduling_group(), [this] {
- complete_timers(_timers, _expired_timers, [this] {
+ _timers.complete(_expired_timers, [this] {
if (!_timers.empty()) {
enable_timer(_timers.get_next_timeout());
}
@@ -2746,7 +2716,7 @@ bool
reactor::do_expire_lowres_timers() noexcept {
auto now = lowres_clock::now();
if (now >= _lowres_next_timeout) {
- complete_timers(_lowres_timers, _expired_lowres_timers, [this] () noexcept {
+ _lowres_timers.complete(_expired_lowres_timers, [this] () noexcept {
if (!_lowres_timers.empty()) {
_lowres_next_timeout = _lowres_timers.get_next_timeout();
} else {
@@ -2760,7 +2730,7 @@ reactor::do_expire_lowres_timers() noexcept {
void
reactor::expire_manual_timers() noexcept {
- complete_timers(_manual_timers, _expired_manual_timers, [] () noexcept {});
+ _manual_timers.complete(_expired_manual_timers, [] () noexcept {});
}
void
@@ -3203,7 +3173,7 @@ reactor::activate(task_queue& tq) {
}
void reactor::service_highres_timer() noexcept {
- complete_timers(_timers, _expired_timers, [this] () noexcept {
+ _timers.complete(_expired_timers, [this] () noexcept {
if (!_timers.empty()) {
enable_timer(_timers.get_next_timeout());
}
@@ -5184,6 +5154,10 @@ run_in_background(future<> f) {
engine().run_in_background(std::move(f));
}
+void log_timer_callback_exception(std::exception_ptr ex) noexcept {
+ seastar_logger.error("Timer callback failed: {}", std::current_exception());
+}
+
}
#ifdef SEASTAR_TASK_BACKTRACE