#include <wefts_ringbuffer.h>
Inheritance diagram for Wefts::RingBuffer< _T >:
Public Methods | |
RingBuffer (const unsigned long size) throw ( InitError ) | |
Creates the buffer. | |
~RingBuffer () | |
unsigned long | size () const |
Returns the allocated size of the ringbuffer. | |
unsigned long | free () |
Free elements in the buffer. | |
void | write (_T data) |
Waits until space is available in the buffer, and then writes the parameter. | |
_T | read () |
bool | tryWrite (_T data) |
Try to write the data. | |
bool | tryRead (_T &data) |
Try to write the data. | |
void | handleCleanup (int pos) |
Cleanup for deferred cancelation. | |
Private Methods | |
bool | empty () const |
Tells if a ringbuffer is empty. | |
bool | full () const |
Tells if a ringbuffer is empty. | |
void | put (_T data) |
Does the raw job of putting the data into the buffer. | |
_T | get () |
Does the raw job of getting the data from the buffer. | |
Private Attributes | |
Mutex | m_mutex |
Condition | m_rCond |
Condition | m_wCond |
_T * | m_buffer |
The buffer. | |
unsigned long | m_size |
The size of the buffer. | |
unsigned long | m_wPos |
write pointer | |
unsigned long | m_rPos |
read pointer | |
int | m_wWaiting |
writers waiting | |
int | m_rWaiting |
readers waiting |
A synchronized ring buffer is an object that allows safe communications between a set of producers (threads providing data) and a set of consumers (threads willing to receive the data provided).
A ring buffer is made of a finite number of cells, allocated in a buffer that can be read or written from the first to the last element; when an element is read, the read-pointer is moved one step forward; when an element is written, a write pointer is moved forward. When one of this pointers reach the last element, it is moved to the first element again. The buffer is full if the write pointer makes a full loop and reaches the cell pointed by the read pointer, and is empty if the read pointer precedes the write pointer by one position.
Readers and writers are continuosly changing the status of the buffer, so that it is absolutely necessary to handle all the data relative to the pointer with just one mutex: a read MUST NOT HAPPEN while a write is done and vice-versa; also two contemporary reads or writes must be forbidden. But here we have to classes of threads, interested in two different kind of events (or predicates). If the buffer is empty, the readers must wait for it being filled again before to proceed, while if the ring is full, the writers must wait for it having some free position again.
The order in which readers can access the data in the buffer is random and depends from the moment they are awaken by the OS.
Ring buffers can be used in various ways. One way is just to make sure that data needed to be processed is sent to the available processors as fast as one of them is ready, and that none of the produced data is lost.
Another typical use is to allow "pluggin in" of new producers if requests have peaks at some moment of the process, or plug in of new consumers if if the system has a temporary abondance of CPU.
Also, maintaining constant the number of consumers and producers, ring buffers acts as a cushion allowing to have consumers with very different processing time without blocking the thrughput of requests.
Another use is to check prestations of producers and consumers; providing a ringbuffer that has at least an amount of cell greater or equal to the double of the readers, it is possible to write algorithms that try to maintain the "fill" level of the ring buffer around a given percentual; in any moment, the amount of requests left to process is an indicator of the efficiency of the process, so a process having a nearly empty ring buffer may want to "relax" its reading rithm, so to free more CPU for the system without loosing promptness in processing, while a process having a nearly filled ring buffer may want to speed up its operations, or slow down process acceptance.
A ring buffer that stays filled for a too long time can be detected to start disaster recovery operations, to warn the administrators or the users.
Finally, a special kind of ringbuffer, having just one cell, may be used just to queue several requests from different sources, and allow them to pass just one at a time.
|
Creates the buffer. A size greater than zero must be given; if the size is so big that the required memory can't be allocated, or if zero is given as an argument, the constructor throws an InitError. |
|
|
|
Tells if a ringbuffer is empty. This function is private as trying to see if a ringbuffer is full or empty makes sense only from within a read or write call (inside a locked mutex area). |
|
Free elements in the buffer. This number does normay not make sense, if writers and readers are running; it is provided just to debug the code or to have a status when no other thread is working on the this object. Anyhow, it makes a lot of sense if used to periodically check the status of the buffer, and so, of the producer and consumers that are using it, or to produce statistical data, or to monitorize the status of a process etc. |
|
Tells if a ringbuffer is empty. This function is private as trying to see if a ringbuffer is full or empty makes sense only from within a read or write call (inside a locked mutex area). |
|
Does the raw job of getting the data from the buffer. Call it only once a thread knows that a write can be done, and while the thread is holding the mutex. |
|
Cleanup for deferred cancelation.
Implements Wefts::CleanupHandler. |
|
Does the raw job of putting the data into the buffer. Call it only once a thread knows that a write can be done, and while the thread is holding the mutex. |
|
|
|
Returns the allocated size of the ringbuffer.
|
|
Try to write the data. Retrunrs immediatly; if some data is available, it is stored in the parameter, and the method returns true; else the parameter is untouched, and the method returns false. |
|
Try to write the data. Retrunrs immediatly; if the data can't be written, returns false. If the data has been written, return true. |
|
Waits until space is available in the buffer, and then writes the parameter.
|
|
The buffer.
|
|
|
|
|
|
read pointer
|
|
readers waiting
|
|
The size of the buffer.
|
|
|
|
write pointer
|
|
writers waiting
|