示例#1
0
const uint8_t* TMemoryBuffer::borrowSlow(uint8_t* buf, uint32_t* len) {
  rBound_ = wBase_;
  if (available_read() >= *len) {
    *len = available_read();
    return rBase_;
  }
  return NULL;
}
void TMemoryBuffer::computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give) {
  // Correct rBound_ so we can use the fast path in the future.
  rBound_ = wBase_;

  // Decide how much to give.
  uint32_t give = std::min(len, available_read());

  *out_start = rBase_;
  *out_give = give;

  // Preincrement rBase_ so the caller doesn't have to.
  rBase_ += give;
}
void TMemoryBuffer::ensureCanWrite(uint32_t len) {
  // Check available space
  uint32_t avail = available_write();
  if (len <= avail) {
    return;
  }

  if (!owner_) {
    throw TTransportException("Insufficient space in external MemoryBuffer");
  }

  bool copy = false;
  if (observerCount_ > 0) {
    transferOwnership();
    // going to make a copy and shift out consumed data
    copy = true;
  }
  avail = bufferSize_ - available_read();

  // Grow the buffer as necessary.
  uint32_t new_size = bufferSize_;
  while (len > avail) {
    new_size = new_size > 0 ? new_size * 2 : 1;
    if (new_size <= bufferSize_) {
      // overflow
      throw TTransportException("Buffer size exceeded maximum (2GB)");
    }
    avail = available_write() + (new_size - bufferSize_);
  }

  // Allocate into a new pointer so we don't bork ours if it fails.
  void* new_buffer = nullptr;
  ptrdiff_t offset = 0;
  if (copy) {
    /* This is not a memory leak, because an observed buffer still owns the
     * previous buffer pointer.
     *
     * NOTE: If you are seeing a memory issue here, it's probable the
     * buffers are just growing very large and not being freed often.
     * Consider setting setResizeBufferEveryN,
     * setIdleWriteBufferLimit, and setIdleReadBufferLimit.
     * This will likely solve the issue.
     */
    new_buffer = std::malloc(new_size);
    if (new_buffer == nullptr) {
      throw std::bad_alloc();
    }
    // only copy the unconsumed data
    memcpy(new_buffer, rBase_, wBase_ - rBase_);
  } else {
    if (rBase_ != buffer_) {
      // shift data
      memmove(buffer_, rBase_, wBase_ - rBase_);
    }
    if (new_size > bufferSize_) {
      new_buffer = std::realloc(buffer_, new_size);
      if (new_buffer == nullptr) {
        throw std::bad_alloc();
      }
    } else {
      // plenty of space
      new_buffer = buffer_;
    }
  }
  offset = (uint8_t *)new_buffer - rBase_;
  bufferSize_ = new_size;

  buffer_ = (uint8_t *)new_buffer;
  rBase_ += offset;
  rBound_ += offset;
  wBase_ += offset;
  wBound_ = buffer_ + bufferSize_;
}