event/Loop: manage all SocketEvents in a linked list
Not only those which are "ready".
This commit is contained in:
parent
dd94f97572
commit
a14997ffb8
@ -67,6 +67,8 @@ EventLoop::~EventLoop() noexcept
|
||||
{
|
||||
assert(idle.empty());
|
||||
assert(timers.empty());
|
||||
assert(sockets.empty());
|
||||
assert(ready_sockets.empty());
|
||||
}
|
||||
|
||||
#ifdef HAVE_URING
|
||||
@ -117,7 +119,11 @@ EventLoop::AddFD(int fd, unsigned events, SocketEvent &event) noexcept
|
||||
assert(!IsAlive() || IsInside());
|
||||
#endif
|
||||
|
||||
return poll_group.Add(fd, events, &event);
|
||||
if (!poll_group.Add(fd, events, &event))
|
||||
return false;
|
||||
|
||||
sockets.push_back(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -131,12 +137,13 @@ EventLoop::ModifyFD(int fd, unsigned events, SocketEvent &event) noexcept
|
||||
}
|
||||
|
||||
bool
|
||||
EventLoop::RemoveFD(int fd) noexcept
|
||||
EventLoop::RemoveFD(int fd, SocketEvent &event) noexcept
|
||||
{
|
||||
#ifdef HAVE_THREADED_EVENT_LOOP
|
||||
assert(!IsAlive() || IsInside());
|
||||
#endif
|
||||
|
||||
event.unlink();
|
||||
return poll_group.Remove(fd);
|
||||
}
|
||||
|
||||
@ -213,11 +220,13 @@ EventLoop::Wait(Event::Duration timeout) noexcept
|
||||
const auto poll_result =
|
||||
poll_group.ReadEvents(ExportTimeoutMS(timeout));
|
||||
|
||||
ready_sockets.clear();
|
||||
for (size_t i = 0; i < poll_result.GetSize(); ++i) {
|
||||
auto &s = *(SocketEvent *)poll_result.GetObject(i);
|
||||
s.SetReadyFlags(poll_result.GetEvents(i));
|
||||
ready_sockets.push_back(s);
|
||||
auto &socket_event = *(SocketEvent *)poll_result.GetObject(i);
|
||||
socket_event.SetReadyFlags(poll_result.GetEvents(i));
|
||||
|
||||
/* move from "sockets" to "ready_sockets" */
|
||||
socket_event.unlink();
|
||||
ready_sockets.push_back(socket_event);
|
||||
}
|
||||
|
||||
return poll_result.GetSize() > 0;
|
||||
@ -309,10 +318,13 @@ EventLoop::Run() noexcept
|
||||
|
||||
/* invoke sockets */
|
||||
while (!ready_sockets.empty() && !quit) {
|
||||
auto &sm = ready_sockets.front();
|
||||
ready_sockets.pop_front();
|
||||
auto &socket_event = ready_sockets.front();
|
||||
|
||||
sm.Dispatch();
|
||||
/* move from "ready_sockets" back to "sockets" */
|
||||
socket_event.unlink();
|
||||
sockets.push_back(socket_event);
|
||||
|
||||
socket_event.Dispatch();
|
||||
}
|
||||
} while (!quit);
|
||||
|
||||
|
@ -91,18 +91,22 @@ class EventLoop final
|
||||
DeferredList deferred;
|
||||
#endif
|
||||
|
||||
using ReadySocketList =
|
||||
using SocketList =
|
||||
boost::intrusive::list<SocketEvent,
|
||||
boost::intrusive::member_hook<SocketEvent,
|
||||
SocketEvent::ReadyListHook,
|
||||
&SocketEvent::ready_siblings>,
|
||||
boost::intrusive::base_hook<boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>>,
|
||||
boost::intrusive::constant_time_size<false>>;
|
||||
|
||||
/**
|
||||
* A list of scheduled #SocketEvent instances, without those
|
||||
* which are ready (these are in #ready_sockets).
|
||||
*/
|
||||
SocketList sockets;
|
||||
|
||||
/**
|
||||
* A linked list of #SocketEvent instances which have a
|
||||
* non-zero "ready_flags" field, and need to be dispatched.
|
||||
*/
|
||||
ReadySocketList ready_sockets;
|
||||
SocketList ready_sockets;
|
||||
|
||||
#ifdef HAVE_URING
|
||||
std::unique_ptr<Uring::Manager> uring;
|
||||
@ -188,7 +192,7 @@ public:
|
||||
|
||||
bool AddFD(int fd, unsigned events, SocketEvent &event) noexcept;
|
||||
bool ModifyFD(int fd, unsigned events, SocketEvent &event) noexcept;
|
||||
bool RemoveFD(int fd) noexcept;
|
||||
bool RemoveFD(int fd, SocketEvent &event) noexcept;
|
||||
|
||||
/**
|
||||
* Remove the given #SocketEvent after the file descriptor
|
||||
|
@ -69,7 +69,7 @@ SocketEvent::Schedule(unsigned flags) noexcept
|
||||
if (scheduled_flags == 0)
|
||||
success = loop.AddFD(fd.Get(), flags, *this);
|
||||
else if (flags == 0)
|
||||
success = loop.RemoveFD(fd.Get());
|
||||
success = loop.RemoveFD(fd.Get(), *this);
|
||||
else
|
||||
success = loop.ModifyFD(fd.Get(), flags, *this);
|
||||
|
||||
|
@ -45,14 +45,11 @@ class EventLoop;
|
||||
* thread that runs the #EventLoop, except where explicitly documented
|
||||
* as thread-safe.
|
||||
*/
|
||||
class SocketEvent {
|
||||
class SocketEvent final : public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>> {
|
||||
friend class EventLoop;
|
||||
|
||||
EventLoop &loop;
|
||||
|
||||
using ReadyListHook = boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
|
||||
ReadyListHook ready_siblings;
|
||||
|
||||
using Callback = BoundMethod<void(unsigned events) noexcept>;
|
||||
const Callback callback;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user