X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fio%2FIOBuf.cpp;h=7206fc4652e13202d4c796d05d84b138c97ddbc6;hb=29b40639ed7b6b3c47f8c5bafe15265f8c484ef8;hp=500b3b54db10b4778552f9cab403ecac640aaa20;hpb=047e9e39c43e16a9c2221406f85fa3d8221c1f35;p=folly.git diff --git a/folly/io/IOBuf.cpp b/folly/io/IOBuf.cpp index 500b3b54..7206fc46 100644 --- a/folly/io/IOBuf.cpp +++ b/folly/io/IOBuf.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2016 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,18 +20,18 @@ #include +#include +#include +#include +#include + #include #include -#include #include #include -#include +#include #include - -#include -#include -#include -#include +#include using std::unique_ptr; @@ -79,14 +79,12 @@ void takeOwnershipError(bool freeOnError, void* buf, } } -} // unnamed namespace +} // namespace namespace folly { struct IOBuf::HeapPrefix { - HeapPrefix(uint16_t flg) - : magic(kHeapMagic), - flags(flg) {} + explicit HeapPrefix(uint16_t flg) : magic(kHeapMagic), flags(flg) {} ~HeapPrefix() { // Reset magic to 0 on destruction. This is solely for debugging purposes // to help catch bugs where someone tries to use HeapStorage after it has @@ -114,7 +112,7 @@ struct IOBuf::HeapFullStorage { HeapStorage hs; SharedInfo shared; - std::max_align_t align; + folly::max_align_t align; }; IOBuf::SharedInfo::SharedInfo() @@ -136,7 +134,7 @@ IOBuf::SharedInfo::SharedInfo(FreeFunction fn, void* arg) void* IOBuf::operator new(size_t size) { size_t fullSize = offsetof(HeapStorage, buf) + size; auto* storage = static_cast(malloc(fullSize)); - // operator new is not allowed to return NULL + // operator new is not allowed to return nullptr if (UNLIKELY(storage == nullptr)) { throw std::bad_alloc(); } @@ -163,7 +161,7 @@ void IOBuf::releaseStorage(HeapStorage* storage, uint16_t freeFlags) { DCHECK_EQ((flags & freeFlags), freeFlags); while (true) { - uint16_t newFlags = (flags & ~freeFlags); + uint16_t newFlags = uint16_t(flags & ~freeFlags); if (newFlags == 0) { // The storage space is now unused. Free it. storage->prefix.HeapPrefix::~HeapPrefix(); @@ -210,8 +208,11 @@ IOBuf::IOBuf(CopyBufferOp /* op */, uint64_t minTailroom) : IOBuf(CREATE, headroom + size + minTailroom) { advance(headroom); - memcpy(writableData(), buf, size); - append(size); + if (size > 0) { + assert(buf != nullptr); + memcpy(writableData(), buf, size); + append(size); + } } IOBuf::IOBuf(CopyBufferOp op, ByteRange br, @@ -247,7 +248,7 @@ unique_ptr IOBuf::createCombined(uint64_t capacity) { uint8_t* bufAddr = reinterpret_cast(&storage->align); uint8_t* storageEnd = reinterpret_cast(storage) + mallocSize; - size_t actualCapacity = storageEnd - bufAddr; + size_t actualCapacity = size_t(storageEnd - bufAddr); unique_ptr ret(new (&storage->hs.buf) IOBuf( InternalConstructor(), packFlagsAndSharedInfo(0, &storage->shared), bufAddr, actualCapacity, bufAddr, 0)); @@ -255,7 +256,7 @@ unique_ptr IOBuf::createCombined(uint64_t capacity) { } unique_ptr IOBuf::createSeparate(uint64_t capacity) { - return make_unique(CREATE, capacity); + return std::make_unique(CREATE, capacity); } unique_ptr IOBuf::createChain( @@ -306,9 +307,9 @@ unique_ptr IOBuf::takeOwnership(void* buf, uint64_t capacity, // // Note that we always pass freeOnError as false to the constructor. // If the constructor throws we'll handle it below. (We have to handle - // allocation failures from make_unique too.) - return make_unique(TAKE_OWNERSHIP, buf, capacity, length, - freeFn, userData, false); + // allocation failures from std::make_unique too.) + return std::make_unique( + TAKE_OWNERSHIP, buf, capacity, length, freeFn, userData, false); } catch (...) { takeOwnershipError(freeOnError, buf, freeFn, userData); throw; @@ -329,7 +330,7 @@ IOBuf::IOBuf(WrapBufferOp op, ByteRange br) } unique_ptr IOBuf::wrapBuffer(const void* buf, uint64_t capacity) { - return make_unique(WRAP_BUFFER, buf, capacity); + return std::make_unique(WRAP_BUFFER, buf, capacity); } IOBuf IOBuf::wrapBufferAsValue(const void* buf, uint64_t capacity) { @@ -503,11 +504,15 @@ void IOBuf::prependChain(unique_ptr&& iobuf) { } unique_ptr IOBuf::clone() const { - return make_unique(cloneAsValue()); + return std::make_unique(cloneAsValue()); } unique_ptr IOBuf::cloneOne() const { - return make_unique(cloneOneAsValue()); + return std::make_unique(cloneOneAsValue()); +} + +unique_ptr IOBuf::cloneCoalesced() const { + return std::make_unique(cloneCoalescedAsValue()); } IOBuf IOBuf::cloneAsValue() const { @@ -534,6 +539,36 @@ IOBuf IOBuf::cloneOneAsValue() const { length_); } +IOBuf IOBuf::cloneCoalescedAsValue() const { + if (!isChained()) { + return cloneOneAsValue(); + } + // Coalesce into newBuf + const uint64_t newLength = computeChainDataLength(); + const uint64_t newHeadroom = headroom(); + const uint64_t newTailroom = prev()->tailroom(); + const uint64_t newCapacity = newLength + newHeadroom + newTailroom; + IOBuf newBuf{CREATE, newCapacity}; + newBuf.advance(newHeadroom); + + auto current = this; + do { + if (current->length() > 0) { + DCHECK_NOTNULL(current->data()); + DCHECK_LE(current->length(), newBuf.tailroom()); + memcpy(newBuf.writableTail(), current->data(), current->length()); + newBuf.append(current->length()); + } + current = current->next(); + } while (current != this); + + DCHECK_EQ(newLength, newBuf.length()); + DCHECK_EQ(newHeadroom, newBuf.headroom()); + DCHECK_LE(newTailroom, newBuf.tailroom()); + + return newBuf; +} + void IOBuf::unshareOneSlow() { // Allocate a new buffer for the data uint8_t* buf; @@ -545,7 +580,10 @@ void IOBuf::unshareOneSlow() { // Maintain the same amount of headroom. Since we maintained the same // minimum capacity we also maintain at least the same amount of tailroom. uint64_t headlen = headroom(); - memcpy(buf + headlen, data_, length_); + if (length_ > 0) { + assert(data_ != nullptr); + memcpy(buf + headlen, data_, length_); + } // Release our reference on the old buffer decrementRefcount(); @@ -666,10 +704,13 @@ void IOBuf::coalesceAndReallocate(size_t newHeadroom, IOBuf* current = this; size_t remaining = newLength; do { - assert(current->length_ <= remaining); - remaining -= current->length_; - memcpy(p, current->data_, current->length_); - p += current->length_; + if (current->length_ > 0) { + assert(current->length_ <= remaining); + assert(current->data_ != nullptr); + remaining -= current->length_; + memcpy(p, current->data_, current->length_); + p += current->length_; + } current = current->next_; } while (current != end); assert(remaining == 0); @@ -750,7 +791,7 @@ void IOBuf::reserveSlow(uint64_t minHeadroom, uint64_t minTailroom) { // - If using jemalloc, we can try to expand in place, avoiding a memcpy() // - If not using jemalloc and we don't have too much to copy, // we'll use realloc() (note that realloc might have to copy - // headroom + data + tailroom, see smartRealloc in folly/Malloc.h) + // headroom + data + tailroom, see smartRealloc in folly/memory/Malloc.h) // - Otherwise, bite the bullet and reallocate. if (headroom() + tailroom() >= minHeadroom + minTailroom) { uint8_t* newData = writableBuffer() + minHeadroom; @@ -810,7 +851,10 @@ void IOBuf::reserveSlow(uint64_t minHeadroom, uint64_t minTailroom) { throw std::bad_alloc(); } newBuffer = static_cast(p); - memcpy(newBuffer + minHeadroom, data_, length_); + if (length_ > 0) { + assert(data_ != nullptr); + memcpy(newBuffer + minHeadroom, data_, length_); + } if (sharedInfo()) { freeExtBuffer(); } @@ -886,7 +930,7 @@ void IOBuf::initExtBuffer(uint8_t* buf, size_t mallocSize, uint8_t* infoStart = (buf + mallocSize) - sizeof(SharedInfo); SharedInfo* sharedInfo = new(infoStart) SharedInfo; - *capacityReturn = infoStart - buf; + *capacityReturn = uint64_t(infoStart - buf); *infoReturn = sharedInfo; } @@ -1004,4 +1048,4 @@ bool IOBufEqual::operator()(const IOBuf& a, const IOBuf& b) const { } } -} // folly +} // namespace folly