THRIFT-5114 Simplified reallocation of TMemoryBuffer
Client: cpp
Patch: Mario Emmenlauer
This closes #2030
diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.cpp b/lib/cpp/src/thrift/transport/TBufferTransports.cpp
index 534067f..329d220 100644
--- a/lib/cpp/src/thrift/transport/TBufferTransports.cpp
+++ b/lib/cpp/src/thrift/transport/TBufferTransports.cpp
@@ -361,16 +361,18 @@
}
// Grow the buffer as necessary.
- uint64_t new_size = bufferSize_;
- while (len > avail) {
- new_size = new_size > 0 ? new_size * 2 : 1;
- if (new_size > maxBufferSize_) {
- throw TTransportException(TTransportException::BAD_ARGS,
- "Internal buffer size overflow");
- }
- avail = available_write() + (static_cast<uint32_t>(new_size) - bufferSize_);
+ const uint32_t current_used = bufferSize_ - avail;
+ const uint32_t required_buffer_size = len + current_used;
+ if (required_buffer_size > maxBufferSize_) {
+ throw TTransportException(TTransportException::BAD_ARGS,
+ "Internal buffer size overflow when requesting a buffer of size " + std::to_string(required_buffer_size));
}
+ // Always grow to the next bigger power of two:
+ const double suggested_buffer_size = std::exp2(std::ceil(std::log2(required_buffer_size)));
+ // Unless the power of two exceeds maxBufferSize_:
+ const uint64_t new_size = static_cast<uint64_t>((std::min)(suggested_buffer_size, static_cast<double>(maxBufferSize_)));
+
// Allocate into a new pointer so we don't bork ours if it fails.
auto* new_buffer = static_cast<uint8_t*>(std::realloc(buffer_, static_cast<std::size_t>(new_size)));
if (new_buffer == nullptr) {
@@ -381,6 +383,7 @@
rBound_ = new_buffer + (rBound_ - buffer_);
wBase_ = new_buffer + (wBase_ - buffer_);
wBound_ = new_buffer + new_size;
+ // Note: with realloc() we do not need to free the previous buffer:
buffer_ = new_buffer;
bufferSize_ = static_cast<uint32_t>(new_size);
}