diff options
author | Pierre Ossman <ossman@cendio.se> | 2011-10-25 15:13:13 +0000 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2011-10-25 15:13:13 +0000 |
commit | 4ce51ffc4ec5fb060855dbe17579cbb3d9228e61 (patch) | |
tree | 77a584a327ef2e1ad6d50882943e5605bde10e81 /common/rdr | |
parent | 7d4e88868a1304caafdc6bef84d0e94785f2ddb5 (diff) | |
download | tigervnc-4ce51ffc4ec5fb060855dbe17579cbb3d9228e61.tar.gz tigervnc-4ce51ffc4ec5fb060855dbe17579cbb3d9228e61.zip |
Make socket writes non-blockable. This allows the system to more quickly
return back to the Xorg main loop, meaning that things will be more responsive
in the presence of slow VNC clients.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4735 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'common/rdr')
-rw-r--r-- | common/rdr/FdOutStream.cxx | 77 | ||||
-rw-r--r-- | common/rdr/FdOutStream.h | 9 |
2 files changed, 75 insertions, 11 deletions
diff --git a/common/rdr/FdOutStream.cxx b/common/rdr/FdOutStream.cxx index c84c946f..a6b85e21 100644 --- a/common/rdr/FdOutStream.cxx +++ b/common/rdr/FdOutStream.cxx @@ -50,17 +50,18 @@ using namespace rdr; enum { DEFAULT_BUF_SIZE = 16384 }; -FdOutStream::FdOutStream(int fd_, int timeoutms_, int bufSize_) - : fd(fd_), timeoutms(timeoutms_), +FdOutStream::FdOutStream(int fd_, bool blocking_, int timeoutms_, int bufSize_) + : fd(fd_), blocking(blocking_), timeoutms(timeoutms_), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) { - ptr = start = new U8[bufSize]; + ptr = start = sentUpTo = new U8[bufSize]; end = start + bufSize; } FdOutStream::~FdOutStream() { try { + blocking = true; flush(); } catch (Exception&) { } @@ -71,21 +72,56 @@ void FdOutStream::setTimeout(int timeoutms_) { timeoutms = timeoutms_; } +void FdOutStream::setBlocking(bool blocking_) { + blocking = blocking_; +} + int FdOutStream::length() { - return offset + ptr - start; + return offset + ptr - sentUpTo; +} + +int FdOutStream::bufferUsage() +{ + return ptr - sentUpTo; } void FdOutStream::flush() { - U8* sentUpTo = start; + int timeoutms_; + + if (blocking) + timeoutms_ = timeoutms; + else + timeoutms_ = 0; + while (sentUpTo < ptr) { - int n = writeWithTimeout((const void*) sentUpTo, ptr - sentUpTo); + int n = writeWithTimeout((const void*) sentUpTo, + ptr - sentUpTo, timeoutms_); + + // Timeout? + if (n == 0) { + // If non-blocking then we're done here + if (!blocking) + break; + + // Otherwise try blocking (with possible timeout) + if ((timeoutms_ == 0) && (timeoutms != 0)) { + timeoutms_ = timeoutms; + break; + } + + // Proper timeout + throw TimedOut(); + } + sentUpTo += n; offset += n; } - ptr = start; + // Managed to flush everything? + if (sentUpTo == ptr) + ptr = sentUpTo = start; } @@ -94,8 +130,31 @@ int FdOutStream::overrun(int itemSize, int nItems) if (itemSize > bufSize) throw Exception("FdOutStream overrun: max itemSize exceeded"); + // First try to get rid of the data we have flush(); + // Still not enough space? + if (itemSize > end - ptr) { + // Can we shuffle things around? + // (don't do this if it gains us less than 25%) + if ((sentUpTo - start > bufSize / 4) && + (itemSize < bufSize - (ptr - sentUpTo))) { + memmove(start, sentUpTo, ptr - sentUpTo); + ptr = start + (ptr - sentUpTo); + sentUpTo = start; + } else { + // Have to get rid of more data, so turn off non-blocking + // for a bit... + bool realBlocking; + + realBlocking = blocking; + blocking = true; + flush(); + blocking = realBlocking; + } + } + + // Can we fit all the items asked for? if (itemSize * nItems > end - ptr) nItems = (end - ptr) / itemSize; @@ -112,7 +171,7 @@ int FdOutStream::overrun(int itemSize, int nItems) // select() and write() returning EINTR. // -int FdOutStream::writeWithTimeout(const void* data, int length) +int FdOutStream::writeWithTimeout(const void* data, int length, int timeoutms) { int n; @@ -146,7 +205,7 @@ int FdOutStream::writeWithTimeout(const void* data, int length) if (n < 0) throw SystemException("select",errno); - if (n == 0) throw TimedOut(); + if (n == 0) return 0; do { n = ::write(fd, data, length); diff --git a/common/rdr/FdOutStream.h b/common/rdr/FdOutStream.h index a3e29127..daa88b24 100644 --- a/common/rdr/FdOutStream.h +++ b/common/rdr/FdOutStream.h @@ -31,23 +31,28 @@ namespace rdr { public: - FdOutStream(int fd, int timeoutms=-1, int bufSize=0); + FdOutStream(int fd, bool blocking=true, int timeoutms=-1, int bufSize=0); virtual ~FdOutStream(); void setTimeout(int timeoutms); + void setBlocking(bool blocking); int getFd() { return fd; } void flush(); int length(); + int bufferUsage(); + private: int overrun(int itemSize, int nItems); - int writeWithTimeout(const void* data, int length); + int writeWithTimeout(const void* data, int length, int timeoutms); int fd; + bool blocking; int timeoutms; int bufSize; int offset; U8* start; + U8* sentUpTo; }; } |