diff options
Diffstat (limited to 'Projects/USBtoSerial/Lib/LightweightRingBuff.h')
-rw-r--r-- | Projects/USBtoSerial/Lib/LightweightRingBuff.h | 127 |
1 files changed, 72 insertions, 55 deletions
diff --git a/Projects/USBtoSerial/Lib/LightweightRingBuff.h b/Projects/USBtoSerial/Lib/LightweightRingBuff.h index 2faef43828..cb0f6112a2 100644 --- a/Projects/USBtoSerial/Lib/LightweightRingBuff.h +++ b/Projects/USBtoSerial/Lib/LightweightRingBuff.h @@ -44,10 +44,19 @@ /* Defines: */ /** Size of each ring buffer, in data elements - must be between 1 and 255. */ - #define BUFFER_SIZE 255 + #define BUFFER_SIZE 255 /** Type of data to store into the buffer. */ - #define RingBuff_Data_t uint8_t + #define RingBuff_Data_t uint8_t + + /** Datatype which may be used to store the count of data stored in a buffer, retrieved + * via a call to \ref RingBuffer_GetCount(). + */ + #if (BUFFER_SIZE <= 0xFF) + #define RingBuff_Count_t uint8_t + #else + #define RingBuff_Count_t uint16_t + #endif /* Type Defines: */ /** Type define for a new ring buffer object. Buffers should be initialized via a call to @@ -58,11 +67,11 @@ RingBuff_Data_t Buffer[BUFFER_SIZE]; /**< Internal ring buffer data, referenced by the buffer pointers. */ RingBuff_Data_t* In; /**< Current storage location in the circular buffer */ RingBuff_Data_t* Out; /**< Current retrieval location in the circular buffer */ - uint8_t Count; /**< Total number of bytes stored in the circular buffer */ + RingBuff_Count_t Count; } RingBuff_t; /* Inline Functions: */ - /** Initialises a ring buffer ready for use. Buffers must be initialized via this function + /** Initializes a ring buffer ready for use. Buffers must be initialized via this function * before any operations are called upon them. Already initialized buffers may be reset * by re-initializing them using this function. * @@ -70,75 +79,74 @@ */ static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer) { - Buffer->In = Buffer->Buffer; - Buffer->Out = Buffer->Buffer; - Buffer->Count = 0; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + Buffer->In = Buffer->Buffer; + Buffer->Out = Buffer->Buffer; + } } - /** Atomically determines if the specified ring buffer contains any free space. This should - * be tested before storing data to the buffer, to ensure that no data is lost due to a - * buffer overrun. + /** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed + * by entering an atomic lock on the buffer while the IN and OUT locations are fetched, so that + * the buffer cannot be modified while the computation takes place. This value should be cached + * when reading out the contents of the buffer, so that as small a time as possible is spent + * in an atomic lock. * - * \param[in,out] Buffer Pointer to a ring buffer structure to insert into + * \note The value returned by this function is guaranteed to only be the minimum number of bytes + * stored in the given buffer; this value may change as other threads write new data and so + * the returned number should be used only to determine how many successive reads may safely + * be performed on the buffer. * - * \return Boolean true if the buffer contains no free space, false otherwise - */ - static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer) + * \param[in] Buffer Pointer to a ring buffer structure whose count is to be computed + */ + static inline RingBuff_Count_t RingBuffer_GetCount(RingBuff_t* const Buffer) { - bool IsFull; + RingBuff_Count_t Count; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - IsFull = (Buffer->Count == BUFFER_SIZE); + Count = Buffer->Count; } - return IsFull; + return Count; } - /** Atomically inserts an element into the ring buffer. + /** Atomically determines if the specified ring buffer contains any free space. This should + * be tested before storing data to the buffer, to ensure that no data is lost due to a + * buffer overrun. * * \param[in,out] Buffer Pointer to a ring buffer structure to insert into - * \param[in] Data Data element to insert into the buffer - */ - static inline void RingBuffer_AtomicInsert(RingBuff_t* const Buffer, - const RingBuff_Data_t Data) + * + * \return Boolean true if the buffer contains no free space, false otherwise + */ + static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer) { - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - *Buffer->In = Data; - - if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE]) - Buffer->In = Buffer->Buffer; - - Buffer->Count++; - } + return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE); } - /** Atomically retrieves an element from the ring buffer. + /** Atomically determines if the specified ring buffer contains any data. This should + * be tested before removing data from the buffer, to ensure that the buffer does not + * underflow. * - * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from + * If the data is to be removed in a loop, store the total number of bytes stored in the + * buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable + * to reduce the time spent in atomicity locks. * - * \return Next data element stored in the buffer - */ - static inline RingBuff_Data_t RingBuffer_AtomicRemove(RingBuff_t* const Buffer) + * \param[in,out] Buffer Pointer to a ring buffer structure to insert into + * + * \return Boolean true if the buffer contains no free space, false otherwise + */ + static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer) { - RingBuff_Data_t Data; - - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - Data = *Buffer->Out; - - if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE]) - Buffer->Out = Buffer->Buffer; - - Buffer->Count--; - } - - return Data; + return (RingBuffer_GetCount(Buffer) == 0); } /** Inserts an element into the ring buffer. * + * \note Only one execution thread (main program thread or an ISR) may insert into a single buffer + * otherwise data corruption may occur. Insertion and removal may occur from different execution + * threads. + * * \param[in,out] Buffer Pointer to a ring buffer structure to insert into * \param[in] Data Data element to insert into the buffer */ @@ -149,11 +157,18 @@ if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE]) Buffer->In = Buffer->Buffer; - - Buffer->Count++; + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + Buffer->Count++; + } } - /** Retrieves an element from the ring buffer. + /** Removes an element from the ring buffer. + * + * \note Only one execution thread (main program thread or an ISR) may remove from a single buffer + * otherwise data corruption may occur. Insertion and removal may occur from different execution + * threads. * * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from * @@ -165,11 +180,13 @@ if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE]) Buffer->Out = Buffer->Buffer; - - Buffer->Count--; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + Buffer->Count--; + } + return Data; } #endif - |