diff --git a/src/connection.hpp b/src/connection.hpp index b8a18c8..7d0dc93 100644 --- a/src/connection.hpp +++ b/src/connection.hpp @@ -338,8 +338,8 @@ private: // Direct access methods for Server int getFd() const { return fd_; } - bool hasMessages() const { return !messages_.empty(); } - bool shouldClose() const { return closeConnection_; } + bool has_messages() const { return !messages_.empty(); } + bool should_close() const { return closeConnection_; } size_t getEpollIndex() const { return epoll_index_; } const int fd_; const int64_t id_; diff --git a/src/server.cpp b/src/server.cpp index ee384d5..1db1bcc 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -162,7 +162,7 @@ void Server::receiveConnectionBack(std::unique_ptr connection) { // Re-add the connection to epoll for continued processing struct epoll_event event{}; - if (!connection->hasMessages()) { + if (!connection->has_messages()) { event.events = EPOLLIN | EPOLLONESHOT; } else { event.events = EPOLLOUT | EPOLLONESHOT; @@ -482,12 +482,13 @@ void Server::process_connection_reads(std::unique_ptr &conn, } void Server::process_connection_writes(std::unique_ptr &conn, - int events) { + int /*events*/) { assert(conn); - // Send immediately if we have outgoing messages (either from EPOLLOUT or - // after reading) - if ((events & EPOLLOUT) || ((events & EPOLLIN) && conn->hasMessages())) { - bool had_messages = conn->hasMessages(); + // For simplicity, we always attempt to write when an event fires. We could be + // more precise and skip the write if we detect that we've already seen EAGAIN + // on this connection and we don't have EPOLLOUT. + if (conn->has_messages()) { + bool had_messages = conn->has_messages(); bool error = conn->writeBytes(); if (error) { @@ -504,7 +505,7 @@ void Server::process_connection_writes(std::unique_ptr &conn, } // Check if buffer became empty (transition from non-empty -> empty) - if (had_messages && !conn->hasMessages()) { + if (had_messages && !conn->has_messages()) { handler_.on_write_buffer_drained(conn); // If handler took ownership (conn is now null), return if (!conn) { @@ -513,7 +514,7 @@ void Server::process_connection_writes(std::unique_ptr &conn, } // Check if we should close the connection according to application - if (!conn->hasMessages() && conn->shouldClose()) { + if (!conn->has_messages() && conn->should_close()) { conn.reset(); // Connection should be closed return; } @@ -547,7 +548,7 @@ void Server::process_connection_batch( int fd = conn_ptr->getFd(); struct epoll_event event{}; - if (!conn_ptr->hasMessages()) { + if (!conn_ptr->has_messages()) { event.events = EPOLLIN | EPOLLONESHOT; } else { event.events = EPOLLOUT | EPOLLONESHOT; diff --git a/tools/load_tester.cpp b/tools/load_tester.cpp index 3746fe3..18a12ae 100644 --- a/tools/load_tester.cpp +++ b/tools/load_tester.cpp @@ -248,7 +248,7 @@ struct Connection { } // Match server's connection state management - bool hasMessages() const { return !request.empty(); } + bool has_messages() const { return !request.empty(); } bool error = false; ~Connection() { @@ -698,7 +698,7 @@ int main(int argc, char *argv[]) { // Transfer back to epoll instance. This thread or another thread // will wake when fd is ready - if (conn->hasMessages()) { + if (conn->has_messages()) { events[i].events = EPOLLOUT | EPOLLONESHOT; } else { events[i].events = EPOLLIN | EPOLLONESHOT; @@ -748,7 +748,7 @@ int main(int argc, char *argv[]) { // Try to write once in the connect thread before handing off to network // threads - assert(conn->hasMessages()); + assert(conn->has_messages()); bool writeFinished = conn->writeBytes(); if (conn->error) { continue; // Connection failed, destructor will clean up @@ -766,7 +766,7 @@ int main(int argc, char *argv[]) { event.events = EPOLLIN | EPOLLONESHOT; } else { event.events = - (conn->hasMessages() ? EPOLLOUT : EPOLLIN) | EPOLLONESHOT; + (conn->has_messages() ? EPOLLOUT : EPOLLIN) | EPOLLONESHOT; } // Add to a round-robin selected epoll instance to distribute load