using namespace rdr;
static const size_t DEFAULT_BUF_SIZE = 8192;
+static const size_t MAX_BUF_SIZE = 4 * 1024 * 1024;
BufferedInStream::BufferedInStream()
: bufSize(DEFAULT_BUF_SIZE), offset(0)
{
ptr = end = start = new U8[bufSize];
+ gettimeofday(&lastSizeCheck, NULL);
+ peakUsage = 0;
}
BufferedInStream::~BufferedInStream()
bool BufferedInStream::overrun(size_t needed, bool wait)
{
- if (needed > bufSize)
- throw Exception("BufferedInStream overrun: "
- "requested size of %lu bytes exceeds maximum of %lu bytes",
- (long unsigned)needed, (long unsigned)bufSize);
+ struct timeval now;
+
+ if (needed > bufSize) {
+ size_t newSize;
+ U8* newBuffer;
+
+ if (needed > MAX_BUF_SIZE)
+ throw Exception("BufferedInStream overrun: requested size of "
+ "%lu bytes exceeds maximum of %lu bytes",
+ (long unsigned)needed, (long unsigned)MAX_BUF_SIZE);
+
+ newSize = DEFAULT_BUF_SIZE;
+ while (newSize < needed)
+ newSize *= 2;
+
+ newBuffer = new U8[newSize];
+ memcpy(newBuffer, ptr, end - ptr);
+ delete [] start;
+ bufSize = newSize;
+
+ offset += ptr - start;
+ end = newBuffer + (end - ptr);
+ ptr = start = newBuffer;
+
+ gettimeofday(&lastSizeCheck, NULL);
+ peakUsage = needed;
+ }
+
+ if (needed > peakUsage)
+ peakUsage = needed;
+
+ // Time to shrink an excessive buffer?
+ gettimeofday(&now, NULL);
+ if ((avail() == 0) && (bufSize > DEFAULT_BUF_SIZE) &&
+ ((now.tv_sec < lastSizeCheck.tv_sec) ||
+ (now.tv_sec > (lastSizeCheck.tv_sec + 5)))) {
+ if (peakUsage < (bufSize / 2)) {
+ size_t newSize;
+
+ newSize = DEFAULT_BUF_SIZE;
+ while (newSize < peakUsage)
+ newSize *= 2;
+
+ // We know the buffer is empty, so just reset everything
+ delete [] start;
+ ptr = end = start = new U8[newSize];
+ bufSize = newSize;
+ }
+
+ gettimeofday(&lastSizeCheck, NULL);
+ peakUsage = needed;
+ }
// Do we need to shuffle things around?
if ((bufSize - (ptr - start)) < needed) {
using namespace rdr;
static const size_t DEFAULT_BUF_SIZE = 16384;
+static const size_t MAX_BUF_SIZE = 32 * 1024 * 1024;
BufferedOutStream::BufferedOutStream()
: bufSize(DEFAULT_BUF_SIZE), offset(0)
{
ptr = start = sentUpTo = new U8[bufSize];
end = start + bufSize;
+ gettimeofday(&lastSizeCheck, NULL);
+ peakUsage = 0;
}
BufferedOutStream::~BufferedOutStream()
void BufferedOutStream::flush()
{
+ struct timeval now;
+
while (sentUpTo < ptr) {
size_t len;
// Managed to flush everything?
if (sentUpTo == ptr)
ptr = sentUpTo = start;
+
+ // Time to shrink an excessive buffer?
+ gettimeofday(&now, NULL);
+ if ((sentUpTo == ptr) && (bufSize > DEFAULT_BUF_SIZE) &&
+ ((now.tv_sec < lastSizeCheck.tv_sec) ||
+ (now.tv_sec > (lastSizeCheck.tv_sec + 5)))) {
+ if (peakUsage < (bufSize / 2)) {
+ size_t newSize;
+
+ newSize = DEFAULT_BUF_SIZE;
+ while (newSize < peakUsage)
+ newSize *= 2;
+
+ // We know the buffer is empty, so just reset everything
+ delete [] start;
+ ptr = start = sentUpTo = new U8[newSize];
+ end = start + newSize;
+ bufSize = newSize;
+ }
+
+ gettimeofday(&lastSizeCheck, NULL);
+ peakUsage = 0;
+ }
}
void BufferedOutStream::overrun(size_t needed)
{
- if (needed > bufSize)
- throw Exception("BufferedOutStream overrun: "
- "requested size of %lu bytes exceeds maximum of %lu bytes",
- (long unsigned)needed, (long unsigned)bufSize);
+ size_t totalNeeded, newSize;
+ U8* newBuffer;
// First try to get rid of the data we have
flush();
- // Still not enough space?
- while (needed > avail()) {
- // Can we shuffle things around?
- // (don't do this if it gains us less than 25%)
- if (((size_t)(sentUpTo - start) > bufSize / 4) &&
- (needed < bufSize - (ptr - sentUpTo))) {
- memmove(start, sentUpTo, ptr - sentUpTo);
- ptr = start + (ptr - sentUpTo);
- sentUpTo = start;
- } else {
- size_t len;
-
- len = bufferUsage();
+ // Make note of the total needed space
+ totalNeeded = needed + (ptr - sentUpTo);
- // Have to get rid of more data, so allow the flush to wait...
- flushBuffer(true);
+ if (totalNeeded > peakUsage)
+ peakUsage = totalNeeded;
- offset += len - bufferUsage();
+ // Enough free space now?
+ if (avail() > needed)
+ return;
- // Managed to flush everything?
- if (sentUpTo == ptr)
- ptr = sentUpTo = start;
- }
+ // Can we shuffle things around?
+ if (needed < bufSize - (ptr - sentUpTo)) {
+ memmove(start, sentUpTo, ptr - sentUpTo);
+ ptr = start + (ptr - sentUpTo);
+ sentUpTo = start;
+ return;
}
+
+ // We'll need to allocate more buffer space...
+
+ if (totalNeeded > MAX_BUF_SIZE)
+ throw Exception("BufferedOutStream overrun: requested size of "
+ "%lu bytes exceeds maximum of %lu bytes",
+ (long unsigned)totalNeeded,
+ (long unsigned)MAX_BUF_SIZE);
+
+ newSize = DEFAULT_BUF_SIZE;
+ while (newSize < totalNeeded)
+ newSize *= 2;
+
+ newBuffer = new U8[newSize];
+ memcpy(newBuffer, sentUpTo, ptr - sentUpTo);
+ delete [] start;
+ bufSize = newSize;
+
+ ptr = newBuffer + (ptr - sentUpTo);
+ sentUpTo = start = newBuffer;
+ end = newBuffer + newSize;
+
+ gettimeofday(&lastSizeCheck, NULL);
+ peakUsage = totalNeeded;
}