X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fio%2FIOBuf.cpp;h=35c4e102bf49d85f01dd08af97a65acdbc864df9;hb=18435bce240108397da4ba1ce0b9db317272b7fd;hp=90517aea7d6c0445c7369a754d8cc66ffd6f0167;hpb=929e93d49bfe69a76b848c03aacf4164621dd3dd;p=folly.git diff --git a/folly/io/IOBuf.cpp b/folly/io/IOBuf.cpp index 90517aea..35c4e102 100644 --- a/folly/io/IOBuf.cpp +++ b/folly/io/IOBuf.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2015 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -112,7 +112,7 @@ struct IOBuf::HeapFullStorage { HeapStorage hs; SharedInfo shared; - MaxAlign align; + std::max_align_t align; }; IOBuf::SharedInfo::SharedInfo() @@ -336,6 +336,10 @@ IOBuf::IOBuf(IOBuf&& other) noexcept { *this = std::move(other); } +IOBuf::IOBuf(const IOBuf& other) { + other.cloneInto(*this); +} + IOBuf::IOBuf(InternalConstructor, uintptr_t flagsAndSharedInfo, uint8_t* buf, @@ -413,6 +417,13 @@ IOBuf& IOBuf::operator=(IOBuf&& other) noexcept { return *this; } +IOBuf& IOBuf::operator=(const IOBuf& other) { + if (this != &other) { + *this = IOBuf(other); + } + return *this; +} + bool IOBuf::empty() const { const IOBuf* current = this; do { @@ -541,6 +552,19 @@ void IOBuf::unshareChained() { coalesceSlow(); } +void IOBuf::makeManagedChained() { + assert(isChained()); + + IOBuf* current = this; + while (true) { + current->makeManagedOne(); + current = current->next_; + if (current == this) { + break; + } + } +} + void IOBuf::coalesceSlow() { // coalesceSlow() should only be called if we are part of a chain of multiple // IOBufs. The caller should have already verified this. @@ -698,7 +722,7 @@ void IOBuf::reserveSlow(uint64_t minHeadroom, uint64_t minTailroom) { return; } - size_t newAllocatedCapacity = goodExtBufferSize(newCapacity); + size_t newAllocatedCapacity = 0; uint8_t* newBuffer = nullptr; uint64_t newHeadroom = 0; uint64_t oldHeadroom = headroom(); @@ -708,8 +732,9 @@ void IOBuf::reserveSlow(uint64_t minHeadroom, uint64_t minTailroom) { SharedInfo* info = sharedInfo(); if (info && (info->freeFn == nullptr) && length_ != 0 && oldHeadroom >= minHeadroom) { + size_t headSlack = oldHeadroom - minHeadroom; + newAllocatedCapacity = goodExtBufferSize(newCapacity + headSlack); if (usingJEMalloc()) { - size_t headSlack = oldHeadroom - minHeadroom; // We assume that tailroom is more useful and more important than // headroom (not least because realloc / xallocx allow us to grow the // buffer at the tail, but not at the head) So, if we have more headroom @@ -722,7 +747,6 @@ void IOBuf::reserveSlow(uint64_t minHeadroom, uint64_t minTailroom) { if (xallocx(p, newAllocatedCapacity, 0, 0) == newAllocatedCapacity) { newBuffer = static_cast(p); newHeadroom = oldHeadroom; - newAllocatedCapacity = newAllocatedCapacity; } // if xallocx failed, do nothing, fall back to malloc/memcpy/free } @@ -743,6 +767,7 @@ void IOBuf::reserveSlow(uint64_t minHeadroom, uint64_t minTailroom) { // None of the previous reallocation strategies worked (or we're using // an internal buffer). malloc/copy/free. if (newBuffer == nullptr) { + newAllocatedCapacity = goodExtBufferSize(newCapacity); void* p = malloc(newAllocatedCapacity); if (UNLIKELY(p == nullptr)) { throw std::bad_alloc(); @@ -870,15 +895,37 @@ IOBuf::Iterator IOBuf::cend() const { folly::fbvector IOBuf::getIov() const { folly::fbvector iov; iov.reserve(countChainElements()); + appendToIov(&iov); + return iov; +} + +void IOBuf::appendToIov(folly::fbvector* iov) const { IOBuf const* p = this; do { // some code can get confused by empty iovs, so skip them if (p->length() > 0) { - iov.push_back({(void*)p->data(), folly::to(p->length())}); + iov->push_back({(void*)p->data(), folly::to(p->length())}); } p = p->next(); } while (p != this); - return iov; +} + +size_t IOBuf::fillIov(struct iovec* iov, size_t len) const { + IOBuf const* p = this; + size_t i = 0; + while (i < len) { + // some code can get confused by empty iovs, so skip them + if (p->length() > 0) { + iov[i].iov_base = const_cast(p->data()); + iov[i].iov_len = p->length(); + i++; + } + p = p->next(); + if (p == this) { + return i; + } + } + return 0; } size_t IOBufHash::operator()(const IOBuf& buf) const {