CRingItem

Name

CRingItem -- Encapsulates an item in a ring buffer.

Synopsis


#include <CRingItem.h>
         

            CRingITem
            
  CRingItem(uint16_t type, size_t maxBody = 8192);
            
            
            
               CRingItem(uint16_t type, uint64_t timestamp, uint32_t sourceId, uint32_t  barrierType = 0, 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();
            
            
            
              const bool  hasBodyHeader();
  
               const uint64_t  getEventTimestamp()
          throws std::string;
  
              const uint32_t  getSourceId()
          throws std::string;
  
              const uint32_t  getBarrierType()
          throws std::string;
              void setBodyHeader(uint64_t timestamp, uint32_t sourceId, uint32_t barrierType = 0);
              virtual const std::string  typeName() ();
              virtual  const std::string  toString() ();
  
             
            
            
           
              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(uint16_t type, uint64_t timestamp, uint32_t sourceId, uint32_t barrierType = 0, size_t maxBody = 8192);

Constructs a ring item with a full body header. The timestamp, sourceId and barriereType parameters set the corresponding fields in the body header. The default barrierType of 0 indicates a non-barrier item.

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. Note that this returns a pointer to the body payload, that is the first byte after the Body Header if one is present or the byte after the zero indicating there is no body header if one is not.

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.

const bool hasBodyHeader();

Returns true if the ring item has a body header. Returns false if not. Note that the condition for returning true is that the length of the body header is non zero.

const uint64_t getEventTimestamp() throws std::string;

Returns the value of the timestamp from the items' body header. If hasBodyHeader would return false a string exception containing an explanatory error message is thrown as an exception.

const uint32_t getSourceId() throws std::string;

Returns the source id from the item's body header. If hasBodyHeader would return false a string exception containing an explanatory error message is thrown as an exception.

const uint32_t getBarrierType() throws std::string;

Returns the barrier type of the item. If hasBodyHeader would return false a string exception containing an explanatory error message is thrown as an exception.

void setBodyHeader(uint64_t timestamp, uint32_t sourceId, uint32_t barrierType = 0);

If the item does not yet have a BodyHeader the body contents are moved to make room and the timestramp sourceId and barrierType parameters are used to fill in the corresponding fields of the Body Header. If the item already has a body header, the parameters replace the contents of the body header in place.

Naturally if you have an event item witha potentially large body, it is more efficient to construct it with a body header, even with nonsensical values and then invoke setBodyHeader than it is to construct the item without a body header, fill it in and then invoke setBodyHeader.

virtual const std::string typeName() ();

This virtual method is intended to be overriden in subclasses to provide a textual name of the item type. This method along with toString below are intended to provide support for creating human readable dumps of ring items. If not overriden, the method will produce string like: Unknown (hex-type) where hex-type is the hexadecimal value of the item type code in the ring item header.

virtual const std::string toString() ();

This virtual method is inteded to be overridden in the subclasses to provide a human readable string representation of the item. If not overridden, the body header formatted and the body payload is simply dumped as hexadecimal bytes.

NoteNote
 

The protected method bodyHeaderToString will produce a string that both describes whether or not an item has a body header and the contents of that header if it does. Since that method is protected, base classes may use it to include a formatted body header to their output.

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.