24#include <seastar/core/abort_source.hh>
25#include <seastar/core/future.hh>
26#include <seastar/core/chunked_fifo.hh>
27#include <seastar/util/modules.hh>
39template <
typename Aborter,
typename T>
40concept aborter = std::is_nothrow_invocable_r_v<void, Aborter, T&>;
43template<
typename... T>
45 void operator()(T...) noexcept {};
57template <
typename T,
typename OnAbort = noop_aborter<T>>
58requires aborter<OnAbort, T>
62 std::optional<T> payload;
63 optimized_optional<abort_source::subscription> sub;
64 entry(T&& payload_) : payload(
std::move(payload_)) {}
65 entry(
const T& payload_) : payload(payload_) {}
66 entry(T payload_, abortable_fifo& ef, abort_source& as)
67 : payload(
std::move(payload_))
68 , sub(as.subscribe([this, &ef] () noexcept {
69 ef._on_abort(*payload);
70 payload = std::nullopt;
72 ef.drop_expired_front();
75 entry(entry&& x) =
delete;
76 entry(
const entry& x) =
delete;
83 std::unique_ptr<entry> _front;
86 chunked_fifo<entry> _list;
91 void drop_expired_front() noexcept {
92 while (!_list.empty() && !_list.front().payload) {
95 if (_front && !_front->payload) {
100 abortable_fifo() noexcept = default;
101 abortable_fifo(OnAbort on_abort) noexcept(
std::is_nothrow_move_constructible_v<OnAbort>) : _on_abort(
std::move(on_abort)) {}
103 abortable_fifo(abortable_fifo&& o) noexcept
104 : abortable_fifo(std::move(o._on_abort)) {
106 assert(o._size == 0);
109 abortable_fifo& operator=(abortable_fifo&& o)
noexcept {
111 this->~abortable_fifo();
112 new (
this) abortable_fifo(std::move(o));
122 bool empty() const noexcept {
127 explicit operator bool() const noexcept {
133 T& front() noexcept {
135 return *_front->payload;
137 return *_list.front().payload;
142 const T& front() const noexcept {
144 return *_front->payload;
146 return *_list.front().payload;
152 size_t size() const noexcept {
160 void reserve(
size_t size) {
161 return _list.reserve(size);
166 void push_back(
const T& payload) {
168 _front = std::make_unique<entry>(payload);
170 _list.emplace_back(payload);
177 void push_back(T&& payload) {
179 _front = std::make_unique<entry>(std::move(payload));
181 _list.emplace_back(std::move(payload));
188 void push_back(T&& payload, abort_source& as) {
189 if (as.abort_requested()) {
194 _front = std::make_unique<entry>(std::move(payload), *
this, as);
196 _list.emplace_back(std::move(payload), *
this, as);
202 template<
typename... U>
203 T& emplace_back(U&&... args) {
205 _front = std::make_unique<entry>();
206 _front->payload.emplace(std::forward<U>(args)...);
208 return *_front->payload;
210 _list.emplace_back();
211 _list.back().payload.emplace(std::forward<U>(args)...);
213 return *_list.back().payload;
222 void make_back_abortable(abort_source& as) {
223 entry* e = _front.get();
224 if (!_list.empty()) {
228 auto aborter = [
this, e] ()
noexcept {
229 _on_abort(*e->payload);
230 e->payload = std::nullopt;
232 drop_expired_front();
234 if (as.abort_requested()) {
238 e->sub = as.subscribe(std::move(aborter));
243 void pop_front() noexcept {
250 drop_expired_front();
Seastar API namespace.
Definition: abort_on_ebadf.hh:26