generic_server: Gentle iterator

Add the ability to iterate over the list of connections in a "gentle"
manner, i.e. -- preempting the loop when required.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
This commit is contained in:
Pavel Emelyanov
2021-11-26 15:29:57 +03:00
parent 661c12066b
commit f035313b16
2 changed files with 26 additions and 0 deletions

View File

@@ -11,6 +11,7 @@
#include "to_string.hh"
#include <seastar/core/when_all.hh>
#include <seastar/core/loop.hh>
#include <seastar/core/reactor.hh>
namespace generic_server {
@@ -30,10 +31,26 @@ connection::~connection()
{
--_server._current_connections;
server::connections_list_t::iterator iter = _server._connections_list.iterator_to(*this);
for (auto&& gi : _server._gentle_iterators) {
if (gi.iter == iter) {
gi.iter++;
}
}
_server._connections_list.erase(iter);
_server.maybe_stop();
}
future<> server::for_each_gently(noncopyable_function<void(const connection&)> fn) {
_gentle_iterators.emplace_front(*this);
std::list<gentle_iterator>::iterator gi = _gentle_iterators.begin();
return seastar::do_until([ gi ] { return gi->iter == gi->end; },
[ gi, fn = std::move(fn) ] {
fn(*(gi->iter++));
return make_ready_future<>();
}
).finally([ this, gi ] { _gentle_iterators.erase(gi); });
}
static bool is_broken_pipe_or_connection_reset(std::exception_ptr ep) {
try {
std::rethrow_exception(ep);

View File

@@ -82,6 +82,13 @@ protected:
future<> _stopped = _all_connections_stopped.get_future();
using connections_list_t = boost::intrusive::list<connection>;
connections_list_t _connections_list;
struct gentle_iterator {
connections_list_t::const_iterator iter, end;
gentle_iterator(const server& s) : iter(s._connections_list.begin()), end(s._connections_list.end()) {}
gentle_iterator(const gentle_iterator&) = delete;
gentle_iterator(gentle_iterator&&) = delete;
};
std::list<gentle_iterator> _gentle_iterators;
std::vector<server_socket> _listeners;
public:
@@ -102,6 +109,8 @@ protected:
virtual future<> unadvertise_connection(shared_ptr<connection> conn);
future<> for_each_gently(noncopyable_function<void(const connection&)>);
void maybe_stop();
};