25#include <boost/intrusive/list.hpp>
27#include <seastar/core/future.hh>
28#include <seastar/util/assert.hh>
29#include <seastar/util/std-compat.hh>
30#include <seastar/util/modules.hh>
38#define SEASTAR_GATE_HOLDER_DEBUG
51 virtual const char* what()
const noexcept override {
60 static constexpr const char* _default_what =
"named gate closed";
66 _what = fmt::format(
"{} gate closed", name);
72 virtual const char* what()
const noexcept override {
73 return _what.empty() ? _default_what : _what.c_str();
85 std::optional<promise<>> _stopped;
87#ifdef SEASTAR_GATE_HOLDER_DEBUG
88 void assert_not_held_when_moved()
const noexcept;
89 void assert_not_held_when_destroyed()
const noexcept;
91 void assert_not_held_when_moved()
const noexcept {}
92 void assert_not_held_when_destroyed()
const noexcept {}
100 : _count(std::exchange(x._count, 0)), _stopped(std::exchange(x._stopped, std::nullopt)) {
101 x.assert_not_held_when_moved();
103 gate& operator=(
gate&& x)
noexcept {
105 SEASTAR_ASSERT(!_count &&
"gate reassigned with outstanding requests");
106 x.assert_not_held_when_moved();
107 _count = std::exchange(x._count, 0);
108 _stopped = std::exchange(x._stopped, std::nullopt);
113 SEASTAR_ASSERT(!_count &&
"gate destroyed with outstanding requests");
114 assert_not_held_when_destroyed();
121 bool opened = !_stopped;
133 throw_closed_exception();
142 if (!_count && _stopped) {
143 _stopped->set_value();
157 throw_closed_exception();
166 SEASTAR_ASSERT(!_stopped &&
"seastar::gate::close() cannot be called more than once");
167 _stopped = std::make_optional(
promise<>());
169 _stopped->set_value();
171 return _stopped->get_future();
181 return bool(_stopped);
195#ifdef SEASTAR_GATE_HOLDER_DEBUG
196 using member_hook_t = boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
199 void debug_hold_gate()
noexcept {
201 _g->_holders.push_back(*
this);
205 void debug_release_gate()
noexcept {
209 void debug_hold_gate()
noexcept {}
210 void debug_release_gate()
noexcept {}
215 gate* release_gate()
noexcept {
216 auto* g = std::exchange(_g,
nullptr);
218 debug_release_gate();
285 _g = std::move(x).release_gate();
293 if (
auto g = release_gate()) {
309 return is_closed() ? std::nullopt : std::make_optional<holder>(*
this);
313 virtual std::exception_ptr make_closed_exception()
const {
317 template <
typename Func>
318 friend auto try_with_gate(gate&, Func&&) noexcept;
320#ifdef SEASTAR_GATE_HOLDER_DEBUG
321 using holders_list_t = boost::intrusive::list<holder,
322 boost::intrusive::member_hook<holder, holder::member_hook_t, &holder::_link>,
323 boost::intrusive::constant_time_size<false>>;
325 holders_list_t _holders;
328 [[noreturn]]
void throw_closed_exception()
const {
329 std::rethrow_exception(make_closed_exception());
333#ifdef SEASTAR_GATE_HOLDER_DEBUG
335inline void gate::assert_not_held_when_moved() const noexcept {
336 SEASTAR_ASSERT(_holders.empty() &&
"gate moved with outstanding holders");
338inline void gate::assert_not_held_when_destroyed() const noexcept {
339 SEASTAR_ASSERT(_holders.empty() &&
"gate destroyed with outstanding holders");
350 , _name(std::move(name))
356 virtual std::exception_ptr make_closed_exception()
const override {
363template <
typename Func>
366invoke_func_with_gate(
gate::holder&& gh, Func&& func)
noexcept {
367 return futurize_invoke(std::forward<Func>(func)).finally([gh = std::forward<gate::holder>(gh)] {});
381template <
typename Func>
385 return internal::invoke_func_with_gate(g.
hold(), std::forward<Func>(func));
400template <
typename Func>
408 return internal::invoke_func_with_gate(g.hold(), std::forward<Func>(func));
A representation of a possibly not-yet-computed value.
Definition: future.hh:1195
holder(gate &g)
Definition: gate.hh:231
~holder()
Destroy a holder and leave the referenced gate.
Definition: gate.hh:256
holder & operator=(const holder &x) noexcept
Definition: gate.hh:266
holder(holder &&x) noexcept
Definition: gate.hh:251
holder(const holder &x) noexcept
Definition: gate.hh:241
void release() noexcept
Leave the held gate.
Definition: gate.hh:292
holder() noexcept
Definition: gate.hh:227
holder & operator=(holder &&x) noexcept
Definition: gate.hh:282
bool try_enter() noexcept
Definition: gate.hh:120
bool is_closed() const noexcept
Returns whether the gate is closed.
Definition: gate.hh:180
future close() noexcept
Definition: gate.hh:165
size_t get_count() const noexcept
Returns a current number of registered in-progress requests.
Definition: gate.hh:175
void check() const
Definition: gate.hh:155
std::optional< holder > try_hold() noexcept
Definition: gate.hh:308
holder hold()
Definition: gate.hh:301
void enter()
Definition: gate.hh:131
void leave() noexcept
Definition: gate.hh:140
auto with_gate(gate &g, Func &&func)
Definition: gate.hh:384
auto try_with_gate(gate &g, Func &&func) noexcept
Definition: gate.hh:403
future< T > make_exception_future(std::exception_ptr &&value) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1873
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Converts a type to a future type, if it isn't already.
Definition: future.hh:1784