Loading src/event/epoll.cpp +32 −10 Original line number Diff line number Diff line Loading @@ -229,16 +229,23 @@ namespace netplus { ssl* srv = static_cast<ssl*>(_ServerSocket); ccon->slots[0].csock = std::make_unique<ssl>(*srv->_tls.cert_map, -1); } else if (_ServerSocket->_Type == sockettype::QUIC) { // QUIC: Process ONE UDP datagram per epoll event. // The server socket uses level-triggered EPOLLIN, // so epoll_wait fires again immediately if more // datagrams are queued. This lets the event loop // interleave other work (e.g. PING ACK processing) // between datagrams. { // QUIC: accept() drains up to 512 queued datagrams in // one call (see quic::accept). The listener fd is // registered EPOLLONESHOT (see runEventloop) so we're // the only thread servicing it right now — rearm on // scope exit (even if accept() throws) so the next // datagram wakes a thread again. int qfd = _ServerSocket->fd(); struct RearmOnExit { poll* p; int fd; ~RearmOnExit() { try { p->setpollEventsFd(fd, EPOLLIN | EPOLLONESHOT); } catch (...) {} } } rearm{this, qfd}; std::unique_ptr<socket> quic_csock; _ServerSocket->accept(quic_csock, true); } return; } Loading Loading @@ -800,6 +807,21 @@ namespace netplus { epoll_event setevent{}; setevent.events = EPOLLIN; // QUIC multiplexes every client (and all of their ongoing // traffic) over this one UDP socket for the connection's // whole lifetime — unlike TCP/SSL, where only accept() shares // the listener and established connections get their own // EPOLLONESHOT'd fd. Without ONESHOT here, every incoming // datagram wakes all `threads` workers (level-triggered, // shared epoll fd) — and since quic_mtx() is one lock per // listener (see socket.h), only one of them can ever do // anything useful; the rest just contend on that mutex for // nothing. ONESHOT + explicit rearm in ConnectEventHandler // limits servicing to one thread at a time, same as TCP/SSL // already do per-connection. if (ss->_Type == sockettype::QUIC) { setevent.events |= EPOLLONESHOT; } setevent.data.fd = ss->fd(); if (epoll_ctl(_pollFD, EPOLL_CTL_ADD, ss->fd(), &setevent) < 0) { Loading Loading
src/event/epoll.cpp +32 −10 Original line number Diff line number Diff line Loading @@ -229,16 +229,23 @@ namespace netplus { ssl* srv = static_cast<ssl*>(_ServerSocket); ccon->slots[0].csock = std::make_unique<ssl>(*srv->_tls.cert_map, -1); } else if (_ServerSocket->_Type == sockettype::QUIC) { // QUIC: Process ONE UDP datagram per epoll event. // The server socket uses level-triggered EPOLLIN, // so epoll_wait fires again immediately if more // datagrams are queued. This lets the event loop // interleave other work (e.g. PING ACK processing) // between datagrams. { // QUIC: accept() drains up to 512 queued datagrams in // one call (see quic::accept). The listener fd is // registered EPOLLONESHOT (see runEventloop) so we're // the only thread servicing it right now — rearm on // scope exit (even if accept() throws) so the next // datagram wakes a thread again. int qfd = _ServerSocket->fd(); struct RearmOnExit { poll* p; int fd; ~RearmOnExit() { try { p->setpollEventsFd(fd, EPOLLIN | EPOLLONESHOT); } catch (...) {} } } rearm{this, qfd}; std::unique_ptr<socket> quic_csock; _ServerSocket->accept(quic_csock, true); } return; } Loading Loading @@ -800,6 +807,21 @@ namespace netplus { epoll_event setevent{}; setevent.events = EPOLLIN; // QUIC multiplexes every client (and all of their ongoing // traffic) over this one UDP socket for the connection's // whole lifetime — unlike TCP/SSL, where only accept() shares // the listener and established connections get their own // EPOLLONESHOT'd fd. Without ONESHOT here, every incoming // datagram wakes all `threads` workers (level-triggered, // shared epoll fd) — and since quic_mtx() is one lock per // listener (see socket.h), only one of them can ever do // anything useful; the rest just contend on that mutex for // nothing. ONESHOT + explicit rearm in ConnectEventHandler // limits servicing to one thread at a time, same as TCP/SSL // already do per-connection. if (ss->_Type == sockettype::QUIC) { setevent.events |= EPOLLONESHOT; } setevent.data.fd = ss->fd(); if (epoll_ctl(_pollFD, EPOLL_CTL_ADD, ss->fd(), &setevent) < 0) { Loading