Hybrid ICN (hICN) plugin  v21.06-rc0-4-g18fa668
Classes | Public Types | Public Member Functions | Static Public Member Functions | List of all members
utils::MemBuf Class Reference
Inheritance diagram for utils::MemBuf:
Inheritance graph
[legend]

Public Types

enum  CreateOp { CREATE }
 
enum  WrapBufferOp { WRAP_BUFFER }
 
enum  TakeOwnershipOp { TAKE_OWNERSHIP }
 
enum  CopyBufferOp { COPY_BUFFER }
 
using Ptr = std::shared_ptr< MemBuf >
 
typedef void(* FreeFunction) (void *buf, void *userData)
 

Public Member Functions

 MemBuf (CreateOp, std::size_t capacity)
 
 MemBuf (TakeOwnershipOp op, void *buf, std::size_t capacity, FreeFunction freeFn=nullptr, void *userData=nullptr, bool freeOnError=true)
 
 MemBuf (TakeOwnershipOp, void *buf, std::size_t capacity, std::size_t length, FreeFunction freeFn=nullptr, void *userData=nullptr, bool freeOnError=true)
 
 MemBuf (WrapBufferOp op, const void *buf, std::size_t length, std::size_t capacity) noexcept
 
 MemBuf (CopyBufferOp op, const void *buf, std::size_t size, std::size_t headroom=0, std::size_t minTailroom=0)
 
bool empty () const
 
const uint8_t * data () const
 
uint8_t * writableData ()
 
const uint8_t * tail () const
 
uint8_t * writableTail ()
 
std::size_t length () const
 
void setLength (std::size_t length)
 
std::size_t headroom () const
 
std::size_t tailroom () const
 
const uint8_t * buffer () const
 
uint8_t * writableBuffer ()
 
const uint8_t * bufferEnd () const
 
std::size_t capacity () const
 
MemBufnext ()
 
const MemBufnext () const
 
MemBufprev ()
 
const MemBufprev () const
 
void advance (std::size_t amount)
 
void retreat (std::size_t amount)
 
void prepend (std::size_t amount)
 
void append (std::size_t amount)
 
void trimStart (std::size_t amount)
 
void trimEnd (std::size_t amount)
 
void clear ()
 
void reserve (std::size_t minHeadroom, std::size_t minTailroom)
 
bool isChained () const
 
size_t countChainElements () const
 
std::size_t computeChainDataLength () const
 
void prependChain (std::unique_ptr< MemBuf > &&iobuf)
 
void appendChain (std::unique_ptr< MemBuf > &&iobuf)
 
std::unique_ptr< MemBufunlink ()
 
std::unique_ptr< MemBufpop ()
 
std::unique_ptr< MemBufseparateChain (MemBuf *head, MemBuf *tail)
 
bool isShared () const
 
bool isManaged () const
 
bool isManagedOne () const
 
bool isSharedOne () const
 
void unshare ()
 
void unshareOne ()
 
void markExternallyShared ()
 
void markExternallySharedOne ()
 
void makeManaged ()
 
void makeManagedOne ()
 
void gather (std::size_t maxLength)
 
std::unique_ptr< MemBufclone () const
 
MemBuf cloneAsValue () const
 
std::unique_ptr< MemBufcloneOne () const
 
MemBuf cloneOneAsValue () const
 
std::unique_ptr< MemBufcloneCoalesced () const
 
std::unique_ptr< MemBufcloneCoalescedWithHeadroomTailroom (std::size_t newHeadroom, std::size_t newTailroom) const
 
MemBuf cloneCoalescedAsValue () const
 
MemBuf cloneCoalescedAsValueWithHeadroomTailroom (std::size_t newHeadroom, std::size_t newTailroom) const
 
void cloneInto (MemBuf &other) const
 
void cloneOneInto (MemBuf &other) const
 
std::vector< struct iovecgetIov () const
 
void appendToIov (std::vector< struct iovec > *iov) const
 
size_t fillIov (struct iovec *iov, size_t len) const
 
bool ensureCapacity (std::size_t capacity)
 
bool ensureCapacityAndFillUnused (std::size_t capacity, uint8_t placeholder)
 
void * operator new (size_t size)
 
void * operator new (size_t size, void *ptr)
 
void operator delete (void *ptr)
 
void operator delete (void *ptr, void *placement)
 
bool operator== (const MemBuf &other)
 
bool operator!= (const MemBuf &other)
 
 MemBuf () noexcept
 
 MemBuf (MemBuf &&other) noexcept
 
MemBufoperator= (MemBuf &&other) noexcept
 
 MemBuf (const MemBuf &other)
 
MemBufoperator= (const MemBuf &other)
 

Static Public Member Functions

static std::unique_ptr< MemBufcreate (std::size_t capacity)
 
static std::unique_ptr< MemBufcreateCombined (std::size_t capacity)
 
static std::unique_ptr< MemBufcreateSeparate (std::size_t capacity)
 
static std::unique_ptr< MemBufcreateChain (size_t totalCapacity, std::size_t maxBufCapacity)
 
static std::unique_ptr< MemBuftakeOwnership (void *buf, std::size_t capacity, FreeFunction freeFn=nullptr, void *userData=nullptr, bool freeOnError=true)
 
static std::unique_ptr< MemBuftakeOwnership (void *buf, std::size_t capacity, std::size_t length, FreeFunction freeFn=nullptr, void *userData=nullptr, bool freeOnError=true)
 
static std::unique_ptr< MemBufwrapBuffer (const void *buf, std::size_t length, std::size_t capacity)
 
static MemBuf wrapBufferAsValue (const void *buf, std::size_t length, std::size_t capacity) noexcept
 
static std::unique_ptr< MemBufcopyBuffer (const void *buf, std::size_t size, std::size_t headroom=0, std::size_t minTailroom=0)
 
static void destroy (std::unique_ptr< MemBuf > &&data)
 
static std::unique_ptr< MemBufwrapIov (const iovec *vec, size_t count)
 
static std::unique_ptr< MemBuftakeOwnershipIov (const iovec *vec, size_t count, FreeFunction freeFn=nullptr, void *userData=nullptr, bool freeOnError=true)
 

Constructor & Destructor Documentation

◆ MemBuf() [1/2]

utils::MemBuf::MemBuf ( )
noexcept

Allocate a new null buffer.

This can be used to allocate an empty MemBuf on the stack. It will have no space allocated for it. This is generally useful only to later use move assignment to fill out the MemBuf.

◆ MemBuf() [2/2]

utils::MemBuf::MemBuf ( MemBuf &&  other)
noexcept

Move constructor and assignment operator.

In general, you should only ever move the head of an MemBuf chain. Internal nodes in an MemBuf chain are owned by the head of the chain, and should not be moved from. (Technically, nothing prevents you from moving a non-head node, but the moved-to node will replace the moved-from node in the chain. This has implications for ownership, since non-head nodes are owned by the chain head. You are then responsible for relinquishing ownership of the moved-to node, and manually deleting the moved-from node.)

With the move assignment operator, the destination of the move should be the head of an MemBuf chain or a solitary MemBuf not part of a chain. If the move destination is part of a chain, all other MemBufs in the chain will be deleted.

Member Function Documentation

◆ advance()

void utils::MemBuf::advance ( std::size_t  amount)
inline

Shift the data forwards in the buffer.

This shifts the data pointer forwards in the buffer to increase the headroom. This is commonly used to increase the headroom in a newly allocated buffer.

The caller is responsible for ensuring that there is sufficient tailroom in the buffer before calling advance().

If there is a non-zero data length, advance() will use memmove() to shift the data forwards in the buffer. In this case, the caller is responsible for making sure the buffer is unshared, so it will not affect other MemBufs that may be sharing the same underlying buffer.

◆ appendToIov()

void utils::MemBuf::appendToIov ( std::vector< struct iovec > *  iov) const

Update an existing iovec array with the MemBuf data.

New iovecs will be appended to the existing vector; anything already present in the vector will be left unchanged.

Naturally, the returned iovec data will be invalid if you modify the buffer chain.

◆ clone()

std::unique_ptr<MemBuf> utils::MemBuf::clone ( ) const

Return a new MemBuf chain sharing the same data as this chain.

The new MemBuf chain will normally point to the same underlying data buffers as the original chain. (The one exception to this is if some of the MemBufs in this chain contain small internal data buffers which cannot be shared.)

◆ cloneAsValue()

MemBuf utils::MemBuf::cloneAsValue ( ) const

Similar to clone(). But returns MemBuf by value rather than heap-allocating it.

◆ cloneCoalesced()

std::unique_ptr<MemBuf> utils::MemBuf::cloneCoalesced ( ) const

Return a new unchained MemBuf that may share the same data as this chain.

If the MemBuf chain is not chained then the new MemBuf will point to the same underlying data buffer as the original chain. Otherwise, it will clone and coalesce the MemBuf chain.

The new MemBuf will have at least as much headroom as the first MemBuf in the chain, and at least as much tailroom as the last MemBuf in the chain.

Throws std::bad_alloc on error.

◆ cloneCoalescedAsValue()

MemBuf utils::MemBuf::cloneCoalescedAsValue ( ) const

Similar to cloneCoalesced(). But returns MemBuf by value rather than heap-allocating it.

◆ cloneCoalescedAsValueWithHeadroomTailroom()

MemBuf utils::MemBuf::cloneCoalescedAsValueWithHeadroomTailroom ( std::size_t  newHeadroom,
std::size_t  newTailroom 
) const

This is similar to the cloneCoalescedAsValue() method, except this allows to set a headroom and tailroom for the new MemBuf.

◆ cloneCoalescedWithHeadroomTailroom()

std::unique_ptr<MemBuf> utils::MemBuf::cloneCoalescedWithHeadroomTailroom ( std::size_t  newHeadroom,
std::size_t  newTailroom 
) const

This is similar to the cloneCoalesced() method, except this allows to set a headroom and tailroom for the new MemBuf.

◆ cloneInto()

void utils::MemBuf::cloneInto ( MemBuf other) const
inline

Similar to Clone(). But use other as the head node. Other nodes in the chain (if any) will be allocted on heap.

◆ cloneOne()

std::unique_ptr<MemBuf> utils::MemBuf::cloneOne ( ) const

Return a new MemBuf with the same data as this MemBuf.

The new MemBuf returned will not be part of a chain (even if this MemBuf is part of a larger chain).

◆ cloneOneAsValue()

MemBuf utils::MemBuf::cloneOneAsValue ( ) const

Similar to cloneOne(). But returns MemBuf by value rather than heap-allocating it.

◆ cloneOneInto()

void utils::MemBuf::cloneOneInto ( MemBuf other) const
inline

Similar to CloneOne(). But to fill an existing MemBuf instead of a new MemBuf.

◆ copyBuffer()

std::unique_ptr< MemBuf > utils::MemBuf::copyBuffer ( const void *  buf,
std::size_t  size,
std::size_t  headroom = 0,
std::size_t  minTailroom = 0 
)
inlinestatic

Convenience function to create a new MemBuf object that copies data from a user-supplied buffer, optionally allocating a given amount of headroom and tailroom.

◆ createChain()

static std::unique_ptr<MemBuf> utils::MemBuf::createChain ( size_t  totalCapacity,
std::size_t  maxBufCapacity 
)
static

Allocate a new MemBuf chain with the requested total capacity, allocating no more than maxBufCapacity to each buffer.

◆ createCombined()

static std::unique_ptr<MemBuf> utils::MemBuf::createCombined ( std::size_t  capacity)
static

Create a new MemBuf, using a single memory allocation to allocate space for both the MemBuf object and the data storage space.

This saves one memory allocation. However, it can be wasteful if you later need to grow the buffer using reserve(). If the buffer needs to be reallocated, the space originally allocated will not be freed() until the MemBuf object itself is also freed. (It can also be slightly wasteful in some cases where you clone this MemBuf and then free the original MemBuf.)

◆ createSeparate()

static std::unique_ptr<MemBuf> utils::MemBuf::createSeparate ( std::size_t  capacity)
static

Create a new IOBuf, using separate memory allocations for the IOBuf object for the IOBuf and the data storage space.

This requires two memory allocations, but saves space in the long run if you know that you will need to reallocate the data buffer later.

◆ destroy()

static void utils::MemBuf::destroy ( std::unique_ptr< MemBuf > &&  data)
inlinestatic

Convenience function to free a chain of MemBufs held by a unique_ptr.

◆ ensureCapacity()

bool utils::MemBuf::ensureCapacity ( std::size_t  capacity)

Ensure the current MemBuf can hold at least capacity bytes and its memory is contiguous

◆ ensureCapacityAndFillUnused()

bool utils::MemBuf::ensureCapacityAndFillUnused ( std::size_t  capacity,
uint8_t  placeholder 
)

Ensure packet buffer can hold at least 1500 bytes in contiguous memory and fill unused memory with placeholder

◆ fillIov()

size_t utils::MemBuf::fillIov ( struct iovec iov,
size_t  len 
) const

Fill an iovec array with the MemBuf data.

Returns the number of iovec filled. If there are more buffer than iovec, returns 0. This version is suitable to use with stack iovec arrays.

Naturally, the filled iovec data will be invalid if you modify the buffer chain.

◆ gather()

void utils::MemBuf::gather ( std::size_t  maxLength)
inline

Ensure that this chain has at least maxLength bytes available as a contiguous memory range.

This method coalesces whole buffers in the chain into this buffer as necessary until this buffer's length() is at least maxLength.

After coalescing, the MemBuf will have at least as much headroom as the first MemBuf in the chain, and at least as much tailroom as the last MemBuf that was coalesced.

Throws std::bad_alloc or std::overflow_error on error. On error the MemBuf chain will be unmodified. Throws std::overflow_error if maxLength is longer than the total chain length.

Upon return, either enough of the chain was coalesced into a contiguous region, or the entire chain was coalesced. That is, length() >= maxLength || !isChained() is true.

◆ getIov()

std::vector<struct iovec> utils::MemBuf::getIov ( ) const

Return an iovector suitable for e.g. writev()

auto iov = buf->getIov(); auto xfer = writev(fd, iov.data(), iov.size());

Naturally, the returned iovector is invalid if you modify the buffer chain.

◆ isManaged()

bool utils::MemBuf::isManaged ( ) const
inline

Return true if all MemBufs in this chain are managed by the usual refcounting mechanism (and so the lifetime of the underlying memory can be extended by clone()).

◆ isManagedOne()

bool utils::MemBuf::isManagedOne ( ) const
inline

Return true if this MemBuf is managed by the usual refcounting mechanism (and so the lifetime of the underlying memory can be extended by cloneOne()).

◆ isShared()

bool utils::MemBuf::isShared ( ) const
inline

Return true if at least one of the MemBufs in this chain are shared, or false if all of the MemBufs point to unique buffers.

Use isSharedOne() to only check this MemBuf rather than the entire chain.

◆ isSharedOne()

bool utils::MemBuf::isSharedOne ( ) const
inline

Return true if other MemBufs are also pointing to the buffer used by this MemBuf, and false otherwise.

If this MemBuf points at a buffer owned by another (non-MemBuf) part of the code (i.e., if the MemBuf was created using wrapBuffer(), or was cloned from such an MemBuf), it is always considered shared.

This only checks the current MemBuf, and not other MemBufs in the chain.

◆ makeManaged()

void utils::MemBuf::makeManaged ( )
inline

Ensure that the memory that MemBufs in this chain refer to will continue to be allocated for as long as the MemBufs of the chain (or any clone()s created from this point onwards) is alive.

This only has an effect for user-owned buffers (created with the WRAP_BUFFER constructor or wrapBuffer factory function), in which case those buffers are unshared.

◆ makeManagedOne()

void utils::MemBuf::makeManagedOne ( )
inline

Ensure that the memory that this MemBuf refers to will continue to be allocated for as long as this MemBuf (or any clone()s created from this point onwards) is alive.

This only has an effect for user-owned buffers (created with the WRAP_BUFFER constructor or wrapBuffer factory function), in which case those buffers are unshared.

◆ markExternallyShared()

void utils::MemBuf::markExternallyShared ( )

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 MemBuf, before it has been shared with other threads.

◆ markExternallySharedOne()

void utils::MemBuf::markExternallySharedOne ( )
inline

Mark the underlying buffer that this MemBuf 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 MemBuf, before it has been shared with other threads.

◆ operator==()

bool utils::MemBuf::operator== ( const MemBuf other)

Override operator == and !=

◆ pop()

std::unique_ptr<MemBuf> utils::MemBuf::pop ( )
inline

Remove this MemBuf from its current chain and return a unique_ptr to the MemBuf that formerly followed it in the chain.

◆ retreat()

void utils::MemBuf::retreat ( std::size_t  amount)
inline

Shift the data backwards in the buffer.

The caller is responsible for ensuring that there is sufficient headroom in the buffer before calling retreat().

If there is a non-zero data length, retreat() will use memmove() to shift the data backwards in the buffer. In this case, the caller is responsible for making sure the buffer is unshared, so it will not affect other MemBufs that may be sharing the same underlying buffer.

◆ separateChain()

std::unique_ptr<MemBuf> utils::MemBuf::separateChain ( MemBuf head,
MemBuf tail 
)
inline

Remove a subchain from this chain.

Remove the subchain starting at head and ending at tail from this chain.

Returns a unique_ptr pointing to head. (In other words, ownership of the head of the subchain is transferred to the caller.) If the caller ignores the return value and lets the unique_ptr be destroyed, the subchain will be immediately destroyed.

The subchain referenced by the specified head and tail must be part of the same chain as the current MemBuf, but must not contain the current MemBuf. However, the specified head and tail may be equal to each other (i.e., they may be a subchain of length 1).

◆ takeOwnershipIov()

static std::unique_ptr<MemBuf> utils::MemBuf::takeOwnershipIov ( const iovec vec,
size_t  count,
FreeFunction  freeFn = nullptr,
void *  userData = nullptr,
bool  freeOnError = true 
)
static

A helper that takes ownerships a number of iovecs into an MemBuf chain. If count == 0, then a zero length buf is returned. This function never returns nullptr.

◆ unshare()

void utils::MemBuf::unshare ( )
inline

Ensure that this MemBuf has a unique buffer that is not shared by other MemBufs.

unshare() operates on an entire chain of MemBuf objects. If the chain is shared, it may also coalesce the chain when making it unique. If the chain is coalesced, subsequent MemBuf objects in the current chain will be automatically deleted.

Note that buffers owned by other (non-MemBuf) users are automatically considered shared.

Throws std::bad_alloc on error. On error the MemBuf chain will be unmodified.

Currently unshare may also throw std::overflow_error if it tries to coalesce. (TODO: In the future it would be nice if unshare() were smart enough not to coalesce the entire buffer if the data is too large. However, in practice this seems unlikely to become an issue.)

◆ unshareOne()

void utils::MemBuf::unshareOne ( )
inline

Ensure that this MemBuf has a unique buffer that is not shared by other MemBufs.

unshareOne() operates on a single MemBuf object. This MemBuf will have a unique buffer after unshareOne() returns, but other MemBufs in the chain may still be shared after unshareOne() returns.

Throws std::bad_alloc on error. On error the MemBuf will be unmodified.

◆ wrapIov()

static std::unique_ptr<MemBuf> utils::MemBuf::wrapIov ( const iovec vec,
size_t  count 
)
static

A helper that wraps a number of iovecs into an MemBuf chain. If count == 0, then a zero length buf is returned. This function never returns nullptr.


The documentation for this class was generated from the following file: