16#include <seastar/core/bitset-iter.hh>
19#include <boost/intrusive/list.hpp>
29void log_timer_callback_exception(std::exception_ptr)
noexcept;
43template<
typename Timer, boost::
intrusive::list_member_hook<> Timer::*link>
46 using time_point =
typename Timer::time_point;
47 using timer_list_t = boost::intrusive::list<Timer, boost::intrusive::member_hook<Timer, boost::intrusive::list_member_hook<>, link>>;
49 using duration =
typename Timer::duration;
50 using timestamp_t =
typename Timer::duration::rep;
52 static constexpr timestamp_t max_timestamp = std::numeric_limits<timestamp_t>::max();
53 static constexpr int timestamp_bits = std::numeric_limits<timestamp_t>::digits;
56 static constexpr int n_buckets = timestamp_bits + 1;
58 std::array<timer_list_t, n_buckets> _buckets;
62 std::bitset<n_buckets> _non_empty_buckets;
64 static timestamp_t get_timestamp(time_point _time_point)
noexcept
66 return _time_point.time_since_epoch().count();
69 static timestamp_t get_timestamp(Timer&
timer)
noexcept
74 int get_index(timestamp_t timestamp)
const noexcept
76 if (timestamp <= _last) {
80 auto index = bitsets::count_leading_zeros(timestamp ^ _last);
81 assert(index < n_buckets - 1);
85 int get_index(Timer&
timer)
const noexcept
87 return get_index(get_timestamp(
timer));
90 int get_last_non_empty_bucket()
const noexcept
92 return bitsets::get_last_set(_non_empty_buckets);
98 , _next(max_timestamp)
99 , _non_empty_buckets(0)
104 for (
auto&& list : _buckets) {
105 while (!list.empty()) {
106 auto&
timer = *list.begin();
131 auto timestamp = get_timestamp(
timer);
132 auto index = get_index(timestamp);
134 _buckets[index].push_back(
timer);
135 _non_empty_buckets[index] =
true;
137 if (timestamp < _next) {
157 auto index = get_index(
timer);
158 auto& list = _buckets[index];
159 list.erase(list.iterator_to(
timer));
161 _non_empty_buckets[index] =
false;
170 if (
timer._expired) {
171 expired.erase(expired.iterator_to(
timer));
172 timer._expired =
false;
192 timer_list_t
expire(time_point now)
noexcept
195 auto timestamp = get_timestamp(now);
197 if (timestamp < _last) {
201 auto index = get_index(timestamp);
203 for (
int i : bitsets::for_each_set(_non_empty_buckets, index + 1)) {
204 exp.splice(exp.end(), _buckets[i]);
205 _non_empty_buckets[i] =
false;
209 _next = max_timestamp;
211 auto& list = _buckets[index];
212 while (!list.empty()) {
213 auto&
timer = *list.begin();
216 exp.push_back(
timer);
222 _non_empty_buckets[index] = !list.empty();
224 if (_next == max_timestamp && _non_empty_buckets.any()) {
225 for (
auto&
timer : _buckets[get_last_non_empty_bucket()]) {
226 _next = std::min(_next, get_timestamp(
timer));
232 template <
typename EnableFunc>
233 void complete(timer_list_t& expired_timers, EnableFunc&& enable_fn)
noexcept(
noexcept(enable_fn())) {
234 expired_timers =
expire(this->now());
235 for (
auto& t : expired_timers) {
239 while (!expired_timers.empty()) {
240 auto t = &*expired_timers.begin();
241 expired_timers.pop_front();
249 *internal::current_scheduling_group_ptr() = t->_sg;
252 internal::log_timer_callback_exception(std::current_exception());
258 *internal::current_scheduling_group_ptr() = prev_sg;
270 return time_point(duration(std::max(_last, _next)));
278 for (
int i : bitsets::for_each_set(_non_empty_buckets)) {
283 size_t size() const noexcept
286 for (
int i : bitsets::for_each_set(_non_empty_buckets)) {
287 res += _buckets[i].size();
297 return _non_empty_buckets.none();
300 time_point now() noexcept {
Definition: timer-set.hh:44
bool insert(Timer &timer) noexcept
Definition: timer-set.hh:129
void clear() noexcept
Definition: timer-set.hh:276
time_point get_next_timeout() const noexcept
Definition: timer-set.hh:268
void remove(Timer &timer, timer_list_t &expired) noexcept
Definition: timer-set.hh:168
timer_list_t expire(time_point now) noexcept
Definition: timer-set.hh:192
void remove(Timer &timer) noexcept
Definition: timer-set.hh:155
bool empty() const noexcept
Definition: timer-set.hh:295
time_point get_timeout() const noexcept
Definition: timer.hh:217
future now()
Returns a ready future.
Definition: later.hh:35
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
scheduling_group current_scheduling_group() noexcept
Returns the current scheduling group.
Definition: scheduling.hh:397