diff options
author | Max Kellermann <max@duempel.org> | 2013-11-06 20:36:37 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-11-06 21:52:24 +0100 |
commit | 422b8472fec9443250895a281b6b0a20190daa22 (patch) | |
tree | ca6cd030ed408fc891445f0976ab3be7bc46e58b /src/event/FullyBufferedSocket.cxx | |
parent | 5b213b0504849b894cf930474fb1bff7cb34cd70 (diff) | |
download | mpd-422b8472fec9443250895a281b6b0a20190daa22.tar.gz mpd-422b8472fec9443250895a281b6b0a20190daa22.tar.xz mpd-422b8472fec9443250895a281b6b0a20190daa22.zip |
event/FullyBufferedSocket: try to write without extra roundtrip
Postpone the write using IdleMonitor instead of scheduling a write
event. This reduces the number of system calls, because we don't need
to register and unregister the write event in epoll.
Diffstat (limited to 'src/event/FullyBufferedSocket.cxx')
-rw-r--r-- | src/event/FullyBufferedSocket.cxx | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/src/event/FullyBufferedSocket.cxx b/src/event/FullyBufferedSocket.cxx index 6a0df183d..3b8cf3765 100644 --- a/src/event/FullyBufferedSocket.cxx +++ b/src/event/FullyBufferedSocket.cxx @@ -42,7 +42,8 @@ FullyBufferedSocket::DirectWrite(const void *data, size_t length) if (IsSocketErrorAgain(code)) return 0; - Cancel(); + IdleMonitor::Cancel(); + BufferedSocket::Cancel(); if (IsSocketErrorClosed(code)) OnSocketClosed(); @@ -61,6 +62,7 @@ FullyBufferedSocket::Flush() size_t length; const void *data = output.Read(&length); if (data == nullptr) { + IdleMonitor::Cancel(); CancelWrite(); return true; } @@ -71,8 +73,10 @@ FullyBufferedSocket::Flush() output.Consume(nbytes); - if (output.IsEmpty()) + if (output.IsEmpty()) { + IdleMonitor::Cancel(); CancelWrite(); + } return true; } @@ -82,6 +86,9 @@ FullyBufferedSocket::Write(const void *data, size_t length) { assert(IsDefined()); + if (length == 0) + return true; + #if 0 /* TODO: disabled because this would add overhead on some callers (the ones that often), but it may be useful */ @@ -98,6 +105,8 @@ FullyBufferedSocket::Write(const void *data, size_t length) } #endif + const bool was_empty = output.IsEmpty(); + if (!output.Append(data, length)) { // TODO static constexpr Domain buffered_socket_domain("buffered_socket"); @@ -107,30 +116,31 @@ FullyBufferedSocket::Write(const void *data, size_t length) return false; } - ScheduleWrite(); + if (was_empty) + IdleMonitor::Schedule(); return true; } bool FullyBufferedSocket::OnSocketReady(unsigned flags) { - const bool was_empty = output.IsEmpty(); - if (!BufferedSocket::OnSocketReady(flags)) - return false; - - if (was_empty && !output.IsEmpty()) - /* just in case the OnSocketInput() method has added - data to the output buffer: try to send it now - instead of waiting for the next event loop - iteration */ - flags |= WRITE; - if (flags & WRITE) { assert(!output.IsEmpty()); + assert(!IdleMonitor::IsActive()); if (!Flush()) return false; } + if (!BufferedSocket::OnSocketReady(flags)) + return false; + return true; } + +void +FullyBufferedSocket::OnIdle() +{ + if (Flush() && !output.IsEmpty()) + ScheduleWrite(); +} |