#include <wefts_ringbuffer.h>
Inheritance diagram for Wefts::RingBuffer< _T >:
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 continuously 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 two kind 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 the "plug in" of new producers when requests peaks at some moment of the process, or to plug in new consumers if the system has a temporary abundance 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 throughput of requests.
Another use is to check the performance 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 percentage; 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 rhythm, 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.
Public Member Functions | |
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) |
Tries to write the data. | |
bool | tryRead (_T &data) |
Tries to read some data from the buffer. | |
virtual void | handleCleanup (int pos, void *) |
Cleanup for deferred cancellation. | |
Private Member Functions | |
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 |
|
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. If writers and readers are running this number normally does not make sense; it is provided just to debug the code or to have a status when no other thread is working on this object. Anyhow, it makes a lot of sense if used to periodically check the status of the buffer, or to produce statistical data, or to monitor the status of a process etc. In other words it gets significance if used in statistical analysis of the buffer status, while it's punctual value is meaningless.
|
|
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 cancellation. Users must never call this method. 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.
|
|
Tries to read some data from the buffer. This method never waits; if some data is immediately available to be pulled out from the buffer, the parameter value is overwritten and the method retunrs true; else, it returns false, and the parameter is left untouched.
|
|
Tries to write the data. This method never waits; if the data can't be written because the buffer is full, it returns false, else it returns 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
|