CRingItem

Name

CRingItem -- Encapsulates an item in a ring buffer.

Synopsis


#include <CRingItem.h>
         
 class CRingITem {

  CRingItem(uint16_t type, size_t maxBody = 8192);
  CRingItem(const CRingItem& rhs);

  virtual ~CRingItem();

  CRingItem& operator=(const CRingItem& rhs);
  const int operator==(const CRingItem& rhs);
  const int operator!=(const CRingItem& rhs);
  const size_t getStorageSize();
   const size_t getBodySize();
  void* getBodyPointer();
  void*  getBodyCursor();
  _RingItem* getItemPointer();
  const uint32_t type();
  void setBodyCursor(void* pNewCursor);
  void commitToRing(CRingBuffer& ring);
  const bool mustSwap();
  static CRingItem* getFromRing(CRingBuffer& ring, CRingSelectionPredicate& predicate);
}

Description

CRingItem is the base class of a hierarchy of classes that encapsulate the format of items put in ring buffers by the NSCL DAQ readout frameworks.

The class hierarchy as a whole is intended both to help application writers format item to be submitted to a ring buffer and to fetch and decode items from a ring buffer. The fetch logic works closely with the set of classes derived from CRingSelectionPredicate to support selective reception of data inserted by a producer program.

Public member functions

CRingItem(uint16_t type, size_t maxBody = 8192);

Constructs a Ring Item. type initializes the type field of the item, and maximum size of the body is set to be maxBody.

The size of the actual ring buffer item placed in a ring via commitToRing is computed from the position of the body cursor as set by the last invocation of setBodyCursor.

In order to reduce the amount of dynamic memory management required for ring buffer items, a static buffer of size CRingItemStaticBufferSize is carried by all objects. Only if the maximum size is requested to be larger than that is a dynamically allocated body produced by the constructor and deleted by the destructor.

CRingItem(const CRingItem& rhs);

Constructs a ring item by creating a functional copy of rhs (copy construction).

CRingItem& operator=(const CRingItem& rhs);

Makes the current object (on the left hand side of an assignment statement) a functional equivalent of rhs.

const int operator==(const CRingItem& rhs);

Compares the object on the left hand side of an == to rhs for functional equivalence. If the two objects reasonably represent the same ring item, returns nonzero, else returns zero.

const int operator!=(const CRingItem& rhs);

Computes the logical inverse of operator==

const size_t getStorageSize();

Returns the total size available for the ring item, header and body together.

const size_t getBodySize();

Returns the amount of data in the body of the ring.

void* getBodyPointer();

Returns a pointer to the start of the body.

void* getBodyCursor();

Returns the last stored body cursor. This is intended to allow you (along with setBodyCursor) to keep track of where you should next add information to a ring item.

_RingItem* getItemPointer();

Returns a pointer to the items storage. This should be a RingItemHeader followed by whatever has been put in the body.

const uint32_t type();

Returns the type of the item encapsulated by the object. This member does account for byte order mismatches in the event the generating system had a different byte order than the system running the object.

void setBodyCursor(void* pNewCursor);

Items have a bodyCursor. This is intended to allow software that is building up an item to keep track of the next free hunk of memory in the item. The cusor can be fetched via getBodyCursor and stored back via setBodyCursor which sets the body cursor to pNewCursor

This is intended as a performance compromise that enables data such as physics events to insert data into items with no penalty other than a pointer dereference. The body cursor is also used to compute the size of an item when it is requested, and when or if it is committed to a ring buffer.

void commitToRing(CRingBuffer& ring);

Inserts the item that is encapsulated by the object into the ring buffer represented by the object ring. At this time, the body cursor must point to the first unused byte following the body, as it is used to calculate the size field of the item.

This call may block indefinitely if space is not available in the ring.

const bool mustSwap();

Returns true if the byte order of the object is the opposite of the running system. Two assumptions are used to derive this result. First, that all ring items that are formatted in the local host will have local host byte ordering and therefore should return false for mustSwap. Second, that the top 16 bits of the data type are always zero and that this can be used to determine the byte ordering of an item.

static CRingItem* getFromRing(CRingBuffer& ring, CRingSelectionPredicate& predicate);

Returns a pointer to a dynamically allocated ring item that was fetched from the ring buffer ring. The item must satisfy the selection criteria defined by predicate. If you want all items, simply pass in an un-reconfigured CAllButPredicate object.

Predicates provide a powerful mechanism for selecting and sampling data from ring buffers. For more information about them, see the chapter Ring Format which provides background information about ring buffer predicates. For reference information, see the reference pages for: CRingSelectionPredicate, CAllButPredicate, and CDesiredTypesPredicate. Note that you may also construct your own predicate classes should these not be sufficient to meet your needs.

The caller is responsible for deleting the object.

Types and public data

While not explicitly referenced in the public interfaces of CRingItem, if you use this class directly, you should be familiar with the data types defined in the header DataFormat.h. These are described fully in the chapter: Ring Format.

EXAMPLES

The code fragment below shows how to sample the next physics buffer from a ring which is represented by the object ring

Example 1. Selecting sampled event from a ring.


#include <DataFormat.h>                            (1)
...
CDesiredTypesPredicate sampledEventsOnly;                (2)
sampledEventsOnly.addDesiredType(PHYSICS_EVENT, true);   (3)
CRingItem* item = CRingItem::getFromRing(ring, sampledEventsOnly); (4)

// work with the item...
                                                        (5)
//  Done with the item.

delete item;                                           (6)
            
(1)
This #include obtains the data type and constant definitions for ring items. Specifically, we wil need at least the PHYSICS_EVENT constant.
(2)
We will limit the ring items processed to the most recently inserted physics event items. This requires a predicate that will select those items. The simplest one to use is the CDesiredTypesPredicate which selects only the types we tell it to in the mode requested.
(3)
This line informs the predicate that we want to select ring items of type PHYSICS_EVENT only and in sampled mode meaning the predicate will skip all but the most recently inserted physics event.
(4)
This gets a pointer to the ring item that satisfies our selection criteria. Note that given our predicate, we are assured that item->type() would return PHYSICS_EVENT.
(5)
I'm omitting what you do to process the item as that's application dependent.
(6)
Once you are done processing the ring item, it's storage must be deleted or else eventually the memory leak you would introduce will cause your program to fail.