Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   Related Pages  

Wefts::RingBuffer< _T > Class Template Reference
[Advanced Syncronization constructs]

Ring buffer synchronization object. More...

#include <wefts_ringbuffer.h>

Inheritance diagram for Wefts::RingBuffer< _T >:

Inheritance graph
[legend]
Collaboration diagram for Wefts::RingBuffer< _T >:

Collaboration graph
[legend]
List of all members.

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


Detailed Description

template<typename _T>
class Wefts::RingBuffer< _T >

Ring buffer synchronization object.

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.

Todo:
variable lenght ringbuffers


Constructor & Destructor Documentation

template<typename _T>
Wefts::RingBuffer< _T >::RingBuffer const unsigned long    size throw ( InitError ) [inline]
 

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.

template<typename _T>
Wefts::RingBuffer< _T >::~RingBuffer   [inline]
 


Member Function Documentation

template<typename _T>
bool Wefts::RingBuffer< _T >::empty   const [inline, private]
 

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).

template<typename _T>
unsigned long Wefts::RingBuffer< _T >::free   [inline]
 

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.

template<typename _T>
bool Wefts::RingBuffer< _T >::full   const [inline, private]
 

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).

template<typename _T>
_T Wefts::RingBuffer< _T >::get   [inline, private]
 

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.

template<typename _T>
void Wefts::RingBuffer< _T >::handleCleanup int    pos [inline, virtual]
 

Cleanup for deferred cancelation.

Implements Wefts::CleanupHandler.

template<typename _T>
void Wefts::RingBuffer< _T >::put _T    data [inline, private]
 

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.

template<typename _T>
_T Wefts::RingBuffer< _T >::read   [inline]
 

template<typename _T>
unsigned long Wefts::RingBuffer< _T >::size   const [inline]
 

Returns the allocated size of the ringbuffer.

template<typename _T>
bool Wefts::RingBuffer< _T >::tryRead _T &    data [inline]
 

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.

template<typename _T>
bool Wefts::RingBuffer< _T >::tryWrite _T    data [inline]
 

Try to write the data.

Retrunrs immediatly; if the data can't be written, returns false. If the data has been written, return true.

template<typename _T>
void Wefts::RingBuffer< _T >::write _T    data [inline]
 

Waits until space is available in the buffer, and then writes the parameter.


Member Data Documentation

template<typename _T>
_T* Wefts::RingBuffer< _T >::m_buffer [private]
 

The buffer.

template<typename _T>
Mutex Wefts::RingBuffer< _T >::m_mutex [private]
 

template<typename _T>
Condition Wefts::RingBuffer< _T >::m_rCond [private]
 

template<typename _T>
unsigned long Wefts::RingBuffer< _T >::m_rPos [private]
 

read pointer

template<typename _T>
int Wefts::RingBuffer< _T >::m_rWaiting [private]
 

readers waiting

template<typename _T>
unsigned long Wefts::RingBuffer< _T >::m_size [private]
 

The size of the buffer.

template<typename _T>
Condition Wefts::RingBuffer< _T >::m_wCond [private]
 

template<typename _T>
unsigned long Wefts::RingBuffer< _T >::m_wPos [private]
 

write pointer

template<typename _T>
int Wefts::RingBuffer< _T >::m_wWaiting [private]
 

writers waiting


The documentation for this class was generated from the following file:
Generated on Mon Aug 18 05:53:47 2003 for Wefts by doxygen1.2.18