X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=folly%2Fio%2FIOBuf.h;h=15f8839c840edb0556cf411e368aa3d69a455a4d;hb=630673beeb35e790ed27c38ea5abe1f5436cb08e;hp=5262fb5f5b70e4d76aaa74947299130408e12c89;hpb=321542683a01c3f334047531e9b487f047129775;p=folly.git diff --git a/folly/io/IOBuf.h b/folly/io/IOBuf.h index 5262fb5f..15f8839c 100644 --- a/folly/io/IOBuf.h +++ b/folly/io/IOBuf.h @@ -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. @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef FOLLY_IO_IOBUF_H_ -#define FOLLY_IO_IOBUF_H_ +#pragma once #include #include @@ -25,7 +24,6 @@ #include #include #include -#include #include #include @@ -33,6 +31,7 @@ #include #include #include +#include // Ignore shadowing warnings within this file, so includers can use -Wshadow. #pragma GCC diagnostic push @@ -372,6 +371,16 @@ class IOBuf { static std::unique_ptr wrapBuffer(ByteRange br) { return wrapBuffer(br.data(), br.size()); } + + /** + * Similar to wrapBuffer(), but returns IOBuf by value rather than + * heap-allocating it. + */ + static IOBuf wrapBufferAsValue(const void* buf, uint64_t capacity); + static IOBuf wrapBufferAsValue(ByteRange br) { + return wrapBufferAsValue(br.data(), br.size()); + } + IOBuf(WrapBufferOp op, const void* buf, uint64_t capacity); IOBuf(WrapBufferOp op, ByteRange br); @@ -498,7 +507,7 @@ class IOBuf { * Returns the number of bytes in the buffer before the start of the data. */ uint64_t headroom() const { - return data_ - buffer(); + return uint64_t(data_ - buffer()); } /** @@ -507,7 +516,7 @@ class IOBuf { * Returns the number of bytes in the buffer after the end of the data. */ uint64_t tailroom() const { - return bufferEnd() - tail(); + return uint64_t(bufferEnd() - tail()); } /** @@ -914,6 +923,10 @@ class IOBuf { return true; } + if (UNLIKELY(sharedInfo()->externallyShared)) { + return true; + } + if (LIKELY(!(flags() & kFlagMaybeShared))) { return false; } @@ -973,6 +986,30 @@ class IOBuf { } } + /** + * Mark the underlying buffers in this chain as shared with external memory + * management mechanism. This will make isShared() always returns true. + * + * This function is not thread-safe, and only safe to call immediately after + * creating an IOBuf, before it has been shared with other threads. + */ + void markExternallyShared(); + + /** + * Mark the underlying buffer that this IOBuf refers to as shared with + * external memory management mechanism. This will make isSharedOne() always + * returns true. + * + * This function is not thread-safe, and only safe to call immediately after + * creating an IOBuf, before it has been shared with other threads. + */ + void markExternallySharedOne() { + SharedInfo* info = sharedInfo(); + if (info) { + info->externallyShared = true; + } + } + /** * Ensure that the memory that IOBufs in this chain refer to will continue to * be allocated for as long as the IOBufs of the chain (or any clone()s @@ -1066,6 +1103,12 @@ class IOBuf { */ std::unique_ptr clone() const; + /** + * Similar to clone(). But returns IOBuf by value rather than heap-allocating + * it. + */ + IOBuf cloneAsValue() const; + /** * Return a new IOBuf with the same data as this IOBuf. * @@ -1074,17 +1117,47 @@ class IOBuf { */ std::unique_ptr cloneOne() const; + /** + * Similar to cloneOne(). But returns IOBuf by value rather than + * heap-allocating it. + */ + IOBuf cloneOneAsValue() const; + + /** + * Return a new unchained IOBuf that may share the same data as this chain. + * + * If the IOBuf chain is not chained then the new IOBuf will point to the same + * underlying data buffer as the original chain. Otherwise, it will clone and + * coalesce the IOBuf chain. + * + * The new IOBuf will have at least as much headroom as the first IOBuf in the + * chain, and at least as much tailroom as the last IOBuf in the chain. + * + * Throws std::bad_alloc on error. + */ + std::unique_ptr cloneCoalesced() const; + + /** + * Similar to cloneCoalesced(). But returns IOBuf by value rather than + * heap-allocating it. + */ + IOBuf cloneCoalescedAsValue() const; + /** * Similar to Clone(). But use other as the head node. Other nodes in the * chain (if any) will be allocted on heap. */ - void cloneInto(IOBuf& other) const; + void cloneInto(IOBuf& other) const { + other = cloneAsValue(); + } /** * Similar to CloneOne(). But to fill an existing IOBuf instead of a new * IOBuf. */ - void cloneOneInto(IOBuf& other) const; + void cloneOneInto(IOBuf& other) const { + other = cloneOneAsValue(); + } /** * Return an iovector suitable for e.g. writev() @@ -1198,6 +1271,7 @@ class IOBuf { FreeFunction freeFn; void* userData; std::atomic refcount; + bool externallyShared{false}; }; // Helper structs for use by operator new and delete struct HeapPrefix; @@ -1277,8 +1351,8 @@ class IOBuf { static inline uintptr_t packFlagsAndSharedInfo(uintptr_t flags, SharedInfo* info) { uintptr_t uinfo = reinterpret_cast(info); - DCHECK_EQ(flags & ~kFlagMask, 0); - DCHECK_EQ(uinfo & kFlagMask, 0); + DCHECK_EQ(flags & ~kFlagMask, 0u); + DCHECK_EQ(uinfo & kFlagMask, 0u); return flags | uinfo; } @@ -1288,7 +1362,7 @@ class IOBuf { inline void setSharedInfo(SharedInfo* info) { uintptr_t uinfo = reinterpret_cast(info); - DCHECK_EQ(uinfo & kFlagMask, 0); + DCHECK_EQ(uinfo & kFlagMask, 0u); flagsAndSharedInfo_ = (flagsAndSharedInfo_ & kFlagMask) | uinfo; } @@ -1298,12 +1372,12 @@ class IOBuf { // flags_ are changed from const methods inline void setFlags(uintptr_t flags) const { - DCHECK_EQ(flags & ~kFlagMask, 0); + DCHECK_EQ(flags & ~kFlagMask, 0u); flagsAndSharedInfo_ |= flags; } inline void clearFlags(uintptr_t flags) const { - DCHECK_EQ(flags & ~kFlagMask, 0); + DCHECK_EQ(flags & ~kFlagMask, 0u); flagsAndSharedInfo_ &= ~flags; } @@ -1385,7 +1459,9 @@ inline std::unique_ptr IOBuf::copyBuffer( uint64_t capacity = headroom + size + minTailroom; std::unique_ptr buf = create(capacity); buf->advance(headroom); - memcpy(buf->writableData(), data, size); + if (size != 0) { + memcpy(buf->writableData(), data, size); + } buf->append(size); return buf; } @@ -1426,6 +1502,8 @@ class IOBuf::Iterator : public boost::iterator_facade< } } + Iterator() {} + private: void setVal() { val_ = ByteRange(pos_->data(), pos_->tail()); @@ -1456,8 +1534,8 @@ class IOBuf::Iterator : public boost::iterator_facade< adjustForEnd(); } - const IOBuf* pos_; - const IOBuf* end_; + const IOBuf* pos_{nullptr}; + const IOBuf* end_{nullptr}; ByteRange val_; }; @@ -1467,5 +1545,3 @@ inline IOBuf::Iterator IOBuf::end() const { return cend(); } } // folly #pragma GCC diagnostic pop - -#endif // FOLLY_IO_IOBUF_H_