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 {
64 std::optional<promise<>> _stopped;
66#ifdef SEASTAR_GATE_HOLDER_DEBUG
67 void assert_not_held_when_moved()
const noexcept;
68 void assert_not_held_when_destroyed()
const noexcept;
70 void assert_not_held_when_moved()
const noexcept {}
71 void assert_not_held_when_destroyed()
const noexcept {}
79 : _count(std::exchange(x._count, 0)), _stopped(std::exchange(x._stopped, std::nullopt)) {
80 x.assert_not_held_when_moved();
84 SEASTAR_ASSERT(!_count &&
"gate reassigned with outstanding requests");
85 x.assert_not_held_when_moved();
86 _count = std::exchange(x._count, 0);
87 _stopped = std::exchange(x._stopped, std::nullopt);
92 SEASTAR_ASSERT(!_count &&
"gate destroyed with outstanding requests");
93 assert_not_held_when_destroyed();
100 bool opened = !_stopped;
121 if (!_count && _stopped) {
122 _stopped->set_value();
145 SEASTAR_ASSERT(!_stopped &&
"seastar::gate::close() cannot be called more than once");
146 _stopped = std::make_optional(
promise<>());
148 _stopped->set_value();
150 return _stopped->get_future();
160 return bool(_stopped);
174#ifdef SEASTAR_GATE_HOLDER_DEBUG
175 using member_hook_t = boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
178 void debug_hold_gate()
noexcept {
180 _g->_holders.push_back(*
this);
184 void debug_release_gate()
noexcept {
188 void debug_hold_gate()
noexcept {}
189 void debug_release_gate()
noexcept {}
194 gate* release_gate()
noexcept {
195 auto* g = std::exchange(_g,
nullptr);
197 debug_release_gate();
264 _g = std::move(x).release_gate();
272 if (
auto g = release_gate()) {
288 return is_closed() ? std::nullopt : std::make_optional<holder>(*
this);
292#ifdef SEASTAR_GATE_HOLDER_DEBUG
293 using holders_list_t = boost::intrusive::list<holder,
294 boost::intrusive::member_hook<holder, holder::member_hook_t, &holder::_link>,
295 boost::intrusive::constant_time_size<false>>;
297 holders_list_t _holders;
301#ifdef SEASTAR_GATE_HOLDER_DEBUG
303inline void gate::assert_not_held_when_moved() const noexcept {
304 SEASTAR_ASSERT(_holders.empty() &&
"gate moved with outstanding holders");
306inline void gate::assert_not_held_when_destroyed() const noexcept {
307 SEASTAR_ASSERT(_holders.empty() &&
"gate destroyed with outstanding holders");
313template <
typename Func>
316invoke_func_with_gate(gate::holder&& gh, Func&& func)
noexcept {
317 return futurize_invoke(std::forward<Func>(func)).finally([gh = std::forward<gate::holder>(gh)] {});
331template <
typename Func>
335 return internal::invoke_func_with_gate(g.
hold(), std::forward<Func>(func));
350template <
typename Func>
358 return internal::invoke_func_with_gate(g.hold(), std::forward<Func>(func));
A representation of a possibly not-yet-computed value.
Definition: future.hh:1197
holder(gate &g)
Definition: gate.hh:210
~holder()
Destroy a holder and leave the referenced gate.
Definition: gate.hh:235
holder & operator=(const holder &x) noexcept
Definition: gate.hh:245
holder(holder &&x) noexcept
Definition: gate.hh:230
holder(const holder &x) noexcept
Definition: gate.hh:220
void release() noexcept
Leave the held gate.
Definition: gate.hh:271
holder() noexcept
Definition: gate.hh:206
holder & operator=(holder &&x) noexcept
Definition: gate.hh:261
bool try_enter() noexcept
Definition: gate.hh:99
bool is_closed() const noexcept
Returns whether the gate is closed.
Definition: gate.hh:159
future close() noexcept
Definition: gate.hh:144
size_t get_count() const noexcept
Returns a current number of registered in-progress requests.
Definition: gate.hh:154
void check() const
Definition: gate.hh:134
std::optional< holder > try_hold() noexcept
Definition: gate.hh:287
holder hold()
Definition: gate.hh:280
void enter()
Definition: gate.hh:110
void leave() noexcept
Definition: gate.hh:119
auto with_gate(gate &g, Func &&func)
Definition: gate.hh:334
auto try_with_gate(gate &g, Func &&func) noexcept
Definition: gate.hh:353
future< T > make_exception_future(std::exception_ptr &&value) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1875
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Converts a type to a future type, if it isn't already.
Definition: future.hh:1786