From e0af02afb69e97c89b84d07e939f72244ca39c05 Mon Sep 17 00:00:00 2001 From: Egor Date: Thu, 5 Jun 2025 20:34:14 +0300 Subject: [PATCH] netpoll: merge pollfd and polldata structures --- src/netpoll.cpp | 121 ++++++++++++++++++------------------------------ src/netpoll.h | 10 ++-- 2 files changed, 49 insertions(+), 82 deletions(-) diff --git a/src/netpoll.cpp b/src/netpoll.cpp index 0ed6939..ba6abd6 100644 --- a/src/netpoll.cpp +++ b/src/netpoll.cpp @@ -6,45 +6,22 @@ #include #include +#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member))) + namespace netpoll { struct pollfd { void *assoc; - SOCKET fd; - int type; + uv_os_sock_t fd; + int type, revents, events; + bool dead; + uv_poll_t handle; }; -#define NETPOLL_MAXFDS 1024 static std::vector fds; +static size_t lastptr = 0; -#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member))) -struct polldata { - uv_poll_t uv; - int events, revents, fd, dead; -}; -static polldata *uvpoll[NETPOLL_MAXFDS] = {}; static uv_loop_t *uvloop = 0; -static size_t lastptr = 0; -namespace uvalloc { - static polldata uvpollbuf[NETPOLL_MAXFDS] = {}; - static polldata *freelist = 0; - static polldata *get() { - polldata *p = freelist; - freelist = static_cast(p->uv.data); - if (!p) - abortf("uvalloc::get: out of polldata!\n"); - return p; - } - static void put(polldata *p) { - p->uv.data = freelist; - freelist = p; - } - static void init() { - for (int i = NETPOLL_MAXFDS-1; i >= 0; i--) - put(&uvpollbuf[i]); - } -} void init(void) { - uvalloc::init(); uvloop = uv_default_loop(); } void fini(void) @@ -57,33 +34,34 @@ void fini(void) } static void cb(uv_poll_t *handle, int status, int events) { - struct polldata *poll = container_of(handle, struct polldata, uv); + pollfd *pfd = container_of(handle, pollfd, handle); if (status == 0) { - poll->revents = events; + pfd->revents = events; } uv_poll_stop(handle); if (status == -EBADF) { - fprintf(stderr, "netpoll::cb: %d EBADF!\n", poll->fd); - poll->dead = 1; - poll->revents = poll->events & (UV_READABLE | UV_WRITABLE); + fprintf(stderr, "netpoll::cb: %d EBADF!\n", pfd->fd); + pfd->dead = true; + pfd->revents = pfd->events; } lastptr = 0; } void begin(void) { - for (size_t i = 0; i < fds.size(); i++) { - if (uvpoll[i]->dead == 0) { - uv_poll_start(&uvpoll[i]->uv, uvpoll[i]->events, cb); - uvpoll[i]->revents = 0; + for (pollfd *pfd : fds) { + if (!pfd->dead) { + uv_poll_start(&pfd->handle, pfd->events, cb); + pfd->revents = 0; } else { - uvpoll[i]->revents = uvpoll[i]->events & (UV_READABLE | UV_WRITABLE); + pfd->revents = pfd->events; + lastptr = 0; } } uv_run(uvloop, UV_RUN_ONCE); } bool get(event &out) { - while (lastptr != fds.size() && !uvpoll[lastptr]->revents) { + while (lastptr != fds.size() && !fds[lastptr]->revents) { lastptr++; } if (lastptr == fds.size()) @@ -92,12 +70,13 @@ bool get(event &out) out.assoc = pfd->assoc; out.fd = pfd->fd; out.type = pfd->type; - out.revents = uvpoll[lastptr]->revents; + out.revents = pfd->revents; lastptr++; return true; } -static size_t search(SOCKET fd, bool add) { +static std::vector::iterator search(uv_os_sock_t fd, bool add=false) +{ if (fd == INVALID_SOCKET) abortf("netpoll::search: INVALID_SOCKET\n"); auto it = std::partition_point(fds.begin(), fds.end(), [fd](const auto &p){ return p->fd < fd; }); @@ -105,53 +84,41 @@ static size_t search(SOCKET fd, bool add) { if (found == add) abortf("netpoll::search: duplicate or missing socket\n"); if (add) { - if (fds.size() == NETPOLL_MAXFDS) - abortf("netpoll::add: NETPOLL_MAXFDS limit\n"); + lastptr += int(lastptr >= size_t(it - fds.begin())); it = fds.insert(it, new pollfd()); (*it)->fd = fd; } - return it - fds.begin(); + return it; } -void add(SOCKET fd, int type, void *assoc) +void add(uv_os_sock_t fd, int type, void *assoc) { - size_t i = search(fd, true); - fds[i]->assoc = assoc; - fds[i]->type = type; - struct polldata *poll = uvalloc::get(); - memmove(uvpoll+i+1, uvpoll+i, sizeof(uvpoll[0])*(fds.size()-1-i)); - uvpoll[i] = poll; - poll->events = 0; - poll->revents = 0; - poll->fd = fds[i]->fd; - poll->dead = 0; - uv_poll_init_socket(uvloop, &poll->uv, fds[i]->fd); - if (lastptr >= i) - lastptr++; + pollfd *pfd = *search(fd, true); + pfd->assoc = assoc; + pfd->type = type; + uv_poll_init_socket(uvloop, &pfd->handle, pfd->fd); } -void del_and_close(SOCKET fd) +void del_and_close(uv_os_sock_t fd) { - size_t i = search(fd, false); - uvpoll[i]->events = 0; - struct polldata *poll = uvpoll[i]; - memmove(uvpoll+i, uvpoll+i+1, sizeof(uvpoll[0])*(fds.size()-(i+1))); - uv_close((uv_handle_t *)&poll->uv, [](uv_handle_t *handle){ - struct polldata *p = container_of(handle, struct polldata, uv); - closesocket(p->fd); - uvalloc::put(p); + auto it = search(fd); + pollfd *pfd = *it; + uv_close((uv_handle_t *)&pfd->handle, [](uv_handle_t *handle){ + pollfd *pfd = container_of(handle, pollfd, handle); + closesocket(pfd->fd); + delete pfd; }); - if (lastptr > i) - lastptr--; - delete fds[i]; - fds.erase(fds.begin()+i); + lastptr -= int(lastptr > size_t(it - fds.begin())); + it = fds.erase(it); } -void reg(SOCKET fd, int ev) +void reg(uv_os_sock_t fd, int ev) { - uvpoll[search(fd, false)]->events = ev & (UV_READABLE | UV_WRITABLE); + pollfd *pfd = *search(fd); + pfd->events = ev & (UV_READABLE | UV_WRITABLE); } -void change_type(SOCKET fd, int type) +void change_type(uv_os_sock_t fd, int type) { - fds[search(fd, false)]->type = type; + pollfd *pfd = *search(fd); + pfd->type = type; } } diff --git a/src/netpoll.h b/src/netpoll.h index cc38c14..c8e3649 100644 --- a/src/netpoll.h +++ b/src/netpoll.h @@ -7,15 +7,15 @@ namespace netpoll { struct event { void *assoc; - SOCKET fd; + uv_os_sock_t fd; int type, revents; }; void init(void); void fini(void); -void add(SOCKET fd, int type, void *assoc); -void del_and_close(SOCKET fd); -void reg(SOCKET fd, int ev); -void change_type(SOCKET fd, int type); +void add(uv_os_sock_t fd, int type, void *assoc); +void del_and_close(uv_os_sock_t fd); +void reg(uv_os_sock_t fd, int ev); +void change_type(uv_os_sock_t fd, int type); void begin(void); bool get(event &out); } -- 2.56.0