diff --git a/xbanan/Base.cpp b/xbanan/Base.cpp index ad9a350..10b98bd 100644 --- a/xbanan/Base.cpp +++ b/xbanan/Base.cpp @@ -12,7 +12,6 @@ #include #include -#include struct Selection { @@ -1814,9 +1813,9 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) (void)TRY_REF(get_window(client_info, wid, X_SendEvent)); Client* target_client = nullptr; - for (auto& [_, thingy] : g_epoll_thingies) + for (auto& [_, thingy] : g_pollables) { - if (thingy.type != EpollThingy::Type::Client) + if (thingy.type != Pollable::Type::Client) continue; auto& other_client = thingy.value.get(); if (!other_client.objects.contains(wid)) @@ -1938,47 +1937,11 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) case X_GrabServer: { g_server_grabber_fd = client_info.fd; - - for (const auto& [_, thingy] : g_epoll_thingies) - { - if (thingy.type != EpollThingy::Type::Client) - continue; - - auto& other_client = thingy.value.get(); - if (client_info.fd == other_client.fd) - continue; - - uint32_t events = 0; - if (other_client.has_epollout) - events |= EPOLLOUT; - - epoll_event event { .events = events, .data = { .fd = other_client.fd } }; - epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event); - } - break; } case X_UngrabServer: { g_server_grabber_fd = -1; - - for (const auto& [_, thingy] : g_epoll_thingies) - { - if (thingy.type != EpollThingy::Type::Client) - continue; - - auto& other_client = thingy.value.get(); - if (client_info.fd == other_client.fd) - continue; - - uint32_t events = EPOLLIN; - if (other_client.has_epollout) - events |= EPOLLOUT; - - epoll_event event { .events = events, .data = { .fd = other_client.fd } }; - epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event); - } - break; } case X_QueryPointer: diff --git a/xbanan/Definitions.h b/xbanan/Definitions.h index fd2099c..123fb5b 100644 --- a/xbanan/Definitions.h +++ b/xbanan/Definitions.h @@ -140,7 +140,6 @@ struct Client }; int fd; State state; - bool has_epollout { false }; bool has_bigrequests { false }; CARD16 sequence { 0 }; BAN::Optional pid; @@ -149,7 +148,7 @@ struct Client BAN::HashSet objects; }; -struct EpollThingy +struct Pollable { enum class Type { @@ -172,7 +171,6 @@ extern BAN::HashMap g_atoms_name_to_id; extern BAN::HashMap g_atoms_id_to_name; extern ATOM g_atom_value; -extern int g_epoll_fd; -extern BAN::HashMap g_epoll_thingies; +extern BAN::HashMap g_pollables; extern int g_server_grabber_fd; diff --git a/xbanan/Events.cpp b/xbanan/Events.cpp index 48442a7..b77aeb2 100644 --- a/xbanan/Events.cpp +++ b/xbanan/Events.cpp @@ -7,23 +7,18 @@ #include #include -#include void register_event_fd(int fd, void* data) { - epoll_event event { .events = EPOLLIN, .data = { .fd = fd } }; - epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, fd, &event); - - MUST(g_epoll_thingies.insert(fd, { - .type = EpollThingy::Type::Event, + MUST(g_pollables.insert(fd, { + .type = Pollable::Type::Event, .value = data, })); } void unregister_event_fd(int fd) { - epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, fd, nullptr); - g_epoll_thingies.remove(fd); + g_pollables.remove(fd); } void on_window_close_event(WINDOW wid) diff --git a/xbanan/ExtXRes.cpp b/xbanan/ExtXRes.cpp index d4445f1..3318320 100644 --- a/xbanan/ExtXRes.cpp +++ b/xbanan/ExtXRes.cpp @@ -7,9 +7,9 @@ template static BAN::ErrorOr for_each_client(uint32_t target_spec, const F& callback) { - for (auto [fd, thingy] : g_epoll_thingies) + for (auto [fd, thingy] : g_pollables) { - if (thingy.type != EpollThingy::Type::Client) + if (thingy.type != Pollable::Type::Client) continue; Client& client_info = thingy.value.get(); diff --git a/xbanan/main.cpp b/xbanan/main.cpp index afa380b..44e15da 100644 --- a/xbanan/main.cpp +++ b/xbanan/main.cpp @@ -5,8 +5,8 @@ #include #include +#include #include -#include #include #include #include @@ -92,8 +92,7 @@ BAN::HashMap g_atoms_name_to_id; BAN::HashMap g_atoms_id_to_name; ATOM g_atom_value = XA_LAST_PREDEFINED + 1; -int g_epoll_fd; -BAN::HashMap g_epoll_thingies; +BAN::HashMap g_pollables; int g_server_grabber_fd = -1; @@ -155,22 +154,6 @@ int main() return 1; } - g_epoll_fd = epoll_create1(0); - if (g_epoll_fd == -1) - { - perror("xbanan: epoll_create1"); - return 1; - } - - { - epoll_event event { .events = EPOLLIN, .data = { .ptr = nullptr } }; - if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, server_sock, &event) == -1) - { - perror("xbanan: epoll_ctl"); - return 1; - } - } - #define APPEND_ATOM(name) do { \ MUST(g_atoms_id_to_name.insert(name, #name##_sv.substring(3))); \ MUST(g_atoms_name_to_id.insert(#name##_sv.substring(3), name)); \ @@ -274,9 +257,9 @@ int main() const auto close_client = [](int client_fd) { - auto& epoll_thingy = g_epoll_thingies[client_fd]; - ASSERT(epoll_thingy.type == EpollThingy::Type::Client); - auto& client_info = epoll_thingy.value.get(); + auto& pollable = g_pollables[client_fd]; + ASSERT(pollable.type == Pollable::Type::Client); + auto& client_info = pollable.value.get(); dprintln("client {} disconnected", client_fd); @@ -328,29 +311,11 @@ int main() g_objects.remove(it); } - epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr); - g_epoll_thingies.remove(client_fd); + g_pollables.remove(client_fd); close(client_fd); - if (client_fd == g_server_grabber_fd) - { + if (g_server_grabber_fd == client_fd) g_server_grabber_fd = -1; - - for (const auto& [_, thingy] : g_epoll_thingies) - { - if (thingy.type != EpollThingy::Type::Client) - continue; - - auto& other_client = thingy.value.get(); - - uint32_t events = EPOLLIN; - if (other_client.has_epollout) - events |= EPOLLOUT; - - epoll_event event { .events = events, .data = { .fd = other_client.fd } }; - epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event); - } - } }; Client dummy_client {}; @@ -377,12 +342,37 @@ int main() for (;;) { - epoll_event events[16]; - const int event_count = epoll_wait(g_epoll_fd, events, 16, -1); - - for (int i = 0; i < event_count; i++) + BAN::Vector pollfds; + MUST(pollfds.reserve(g_pollables.size() + 1)); + MUST(pollfds.push_back({ + .fd = server_sock, + .events = POLLIN, + .revents = 0, + })); + for (auto& [fd, pollable] : g_pollables) { - if (events[i].data.ptr == nullptr) + short events = 0; + if (g_server_grabber_fd == -1 || g_server_grabber_fd == fd) + events |= POLLIN; + if (pollable.type == Pollable::Type::Client && !pollable.value.get().output_buffer.empty()) + events |= POLLOUT; + if (events == 0) + continue; + MUST(pollfds.push_back(pollfd { + .fd = fd, + .events = events, + .revents = 0, + })); + } + + const int event_count = poll(pollfds.data(), pollfds.size(), -1); + + for (const auto& pollfd : pollfds) + { + if (pollfd.revents == 0) + continue; + + if (pollfd.fd == server_sock) { int client_sock = accept(server_sock, nullptr, nullptr); if (client_sock == -1) @@ -400,8 +390,8 @@ int main() client_pid = client_cred.pid; #endif - MUST(g_epoll_thingies.insert(client_sock, { - .type = EpollThingy::Type::Client, + MUST(g_pollables.insert(client_sock, { + .type = Pollable::Type::Client, .value = Client { .fd = client_sock, .state = Client::State::ConnectionSetup, @@ -409,44 +399,32 @@ int main() } })); - uint32_t events = 0; - if (g_server_grabber_fd == -1) - events |= EPOLLIN; - - epoll_event event = { .events = events, .data = { .fd = client_sock } }; - if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, client_sock, &event) == -1) - { - perror("xbanan: epoll_ctl"); - close(client_sock); - continue; - } - dprintln("client {} connected", client_sock); continue; } - auto it = g_epoll_thingies.find(events[i].data.fd); - if (it == g_epoll_thingies.end()) + auto it = g_pollables.find(pollfd.fd); + if (it == g_pollables.end()) continue; - auto& epoll_thingy = it->value; + auto& pollable = it->value; - if (epoll_thingy.type == EpollThingy::Type::Event) + if (pollable.type == Pollable::Type::Event) { - g_platform_ops.poll_events(epoll_thingy.value.get()); + g_platform_ops.poll_events(pollable.value.get()); continue; } - ASSERT(epoll_thingy.type == EpollThingy::Type::Client); + ASSERT(pollable.type == Pollable::Type::Client); - auto& client_info = epoll_thingy.value.get(); + auto& client_info = pollable.value.get(); - if (events[i].events & EPOLLHUP) + if (pollfd.revents & POLLHUP) { close_client(client_info.fd); continue; } - if (events[i].events & EPOLLOUT) + if (pollfd.revents & POLLOUT) { const ssize_t nsend = send( client_info.fd, @@ -473,28 +451,11 @@ int main() ); MUST(client_info.output_buffer.resize(client_info.output_buffer.size() - nsend)); - if (client_info.output_buffer.empty()) - { - uint32_t events = 0; - if (g_server_grabber_fd == -1 || g_server_grabber_fd == client_info.fd) - events |= EPOLLIN; - - epoll_event event { .events = events, .data = { .fd = client_info.fd } }; - if (epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, client_info.fd, &event) == -1) - { - perror("xbanan: epoll_ctl"); - close_client(client_info.fd); - continue; - } - - client_info.has_epollout = false; - } - send_done: (void)0; } - if (!(events[i].events & EPOLLIN)) + if (!(pollfd.revents & POLLIN)) continue; if (g_server_grabber_fd != -1 && g_server_grabber_fd != client_info.fd) @@ -606,30 +567,5 @@ int main() } } } - - iterator_invalidated: - for (auto& [_, thingy] : g_epoll_thingies) - { - if (thingy.type != EpollThingy::Type::Client) - continue; - - auto& client_info = thingy.value.get(); - if (client_info.output_buffer.empty() || client_info.has_epollout) - continue; - - uint32_t events = EPOLLOUT; - if (g_server_grabber_fd == -1 || g_server_grabber_fd == client_info.fd) - events |= EPOLLIN; - - epoll_event event { .events = events, .data = { .fd = client_info.fd } }; - if (epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, client_info.fd, &event) == -1) - { - perror("xbanan: epoll_ctl"); - close_client(client_info.fd); - goto iterator_invalidated; - } - - client_info.has_epollout = true; - } } }