CRingBufferChunkAccess

Name

CRingBufferChunkAccess -- Provides zero copy, low level consumer access to ring buffers

Synopsis


class CRingBufferChunkAccess {
public:
    class Chunk {
    public:
        class iterator {
        public:
            iterator(void* pStorage, size_t bytes);
            iterator(const iterator& rhs);
            iterator& operator=(const iterator& rhs);
            bool operator==(const iterator& rhs) const;
            
            pRingItemHeader operator->();
            RingItemHeader& operator*();
            iterator& operator++();         
            iterator  operator++(int);      
        };
        Chunk();
        void setChunk(size_t bytesInChunk, void* pStorage);
    
        void* getStorage();
        size_t size() const;
        iterator begin();
        iterator end();
    };

public:
    CRingBufferChunkAccess(CRingBuffer* pRingBuffer);
    size_t waitChunk(size_t maxChunk, int polls = 0, int usecPoll = 0);
    Chunk nextChunk();
    
};

      

DESCRIPTION

The CRingItem class provides a convenient method to create and commit ring items to a ring buffer as well as to consumer ring items from a ring buffer. The downside of this convenience is that data must be copied, sometimes several times. This class provides consumers with zero copy access to ring items in a ring buffer.

The model is that the user asks for, and eventually gets, a chunk of items. For the most part chunks represent a contiguous block of items in the ring buffer shared memory that have been produced but not yet consumed by this consumer. The user can then create an iterator which allows them to obtain individual items from the chunk.

The class handles the (rare for ring item sizes >> than the typical ring item) case where a ring item wraps by creating a single item chunk that's been copied from the ring buffer into a contiguous block of local memory.

Each invocation of nextChunk releases the ring items the previous chunk contains allowing that storage in the ring buffer to be re-used by the producer.

METHODS of CRingBufferChunkAccess

CRingBufferChunkAccess(CRingBuffer* pRingBuffer);

Constructs a zero copy ring item accessor. pRingBuffer is a pointer to a CRingBuffer object that must have been created as a consumer. If this pointer does not represent a current consumer to the ring buffer, a std::logic_error exception is thrown.

size_t waitChunk(size_t maxChunk, int polls = = 0, int usecPoll = = 0);

Blocks the caller until the appropriate condition is met. The block ends when there's at least maxChunk bytes of data waiting to be consumed by the client. While blocking the client blocks for usecPoll microseconds between each check of the number of bytes available. If polls checks have been done, blocking ends.

Regardless of why or how this method returns, the return value is the number of bytes of data available for consumption. Note that this may, in fact be zero. NSCLDAQ ring items are inserted by our software atomically, which implies that if the return value is nonzero there will be at least one ring item available for consumption.

The defaults for polls means the method will return immediately. The default for usecPoll mean that the program will spin wait. For true blocking, both should be non-zero, where usecPoll*polls determines the maximum wait time and usecPoll the desired maximum latency for ending the block.

CRingBufferChunkAccess::Chunk nextChunk();

Returns the next chunk as a CRingBufferChunkAccess::Chunk object. This chunk is only valid until the next call to nextChunk. The size of the chunk depends on ow much data is available at the time of the call and where the top of the ring buffer is relative to the get pointer for this client.

See CRingBufferChunkAccess::Chunk METHODS below for the methods defined on a chunk.

CRingBufferChunkAccess::Chunk METHODS

Chunk();

Constructs an empty chunk. Note that user code does not need to call this, only the CRingBufferChunkAccess::nextChunk method.

void setChunk(size_t bytesInChunk, void* pStorage);

Sets the pointer and size of the storage associated with a chunk Again, this normally does not have to be called by user level code, CRingBufferChunkAccess::nextChunk will invoke this to initialize the chunk it hands back to the user.

void* getStorage();

Returns the pointer to the chunk's data.

const size_t size();

Returns the number of bytes in the chunk.

CRingBufferChunkAccess::Chunk::iterator begin();

Returns an iterator to the first item in the chunk. See CRingBufferChunkAccess::Chunk::iterator METHODS below for the things you can do with an iterator.

Suffice to say that iterators behave like STL forward iterators.

CRingBufferChunkAccess::Chunk::iterator end();

Returns an end of iteration iterator. This iterator can be though of as pointing just off the end of the chunk.

CRingBufferChunkAccess::Chunk::iterator METHODS

Normally your code does not explicitly construct an iterator. Instead, the CRingBufferChunkAccess::Chunk you got from the ring buffer will be used to construct iterators that allow you to iterate over the ring items in that chunk.

iterator (void* pStorage, size_t bytes);

Constructs an iterator of ring items on an arbitrary chunk of storage. Normally the CRingBufferChunkAccess::Chunk::begin method uses this.

iterator(const iterator& rhs);

Copy constructor for iterators.

iterator& operator=(const iterator& rhs);

Supports assignment of iterators.

const bool operator==(const iterator& rhs);

Supports comparison of two iterators for equality.

pRingItemHeader operator->();

Supports field dereferincing an iterator as if it were a pointer to a Ring item header e.g. given an iterator p, p->s_type is the ring item type.

RingItemHeader& operator*();

Supports dereferencing an iterator as if it were a pointer to a ring item header. For example, given an iterator p, reinterpret_cast<pRingItem>(&(*p)) produces a pointer to the ring item as a whole.

iterator& operator++();

Pre increments an iterator. That is the iterator is incremnted and a reference to the resulting incremented iterator is returned. This is the most efficient increment.

iterator operator++(int );

Supports post incrementing an iterator. A copy of the iterator is produced, the iterator is incremented and a copy of the iterator prior to the increment is returned. In general, this requires two copies of the iterator.

Public Data and Types

size_t CRingBufferChunkAccess::m_RingBufferBytes

Contains the number of bytes in the underlying ring buffer. This should be treated as readonly but for implementation reasons cannot be declared const.