rpa::pipe_circular< Container, CondVar > Class Template Reference

A circular buffer based on any kind of container. More...

#include <pipeline.h>

Inheritance diagram for rpa::pipe_circular< Container, CondVar >:

rpa::pipebase< Container, CondVar > rpa::pipe_container< Container > List of all members.

Public Types

typedef pipebase_t::iterator iterator
typedef pipebase_t::mutex_type mutex_type
typedef pipebase_t::value_type value_type
typedef range_step< pipe_circular,
pipe_circular
range_step_type
typedef pipe_itr< value_type,
reader
sync_iter

Public Member Functions

void check (void) const
 If Not rd_before_wr, then distance will never stops.
 pipe_circular (mutex_type *mtxPtr, size_t maxNb)
template<class Iter>
 pipe_circular (mutex_type *mtxPtr, Iter begIter, Iter endIter, bool shutFlag=true)
 pipe_circular (mutex_type *mtxPtr, const Container &aCont, bool shutFlag=true)
 ~pipe_circular ()
 QUESTION: FOR WHICH REASON ALL WRITERS HAVE FINISHED ?
void push_back (const value_type &aV)
template<class IterIn>
void append (IterIn itBeg, IterIn itEnd, size_t szReserve)
bool data_ready (void) const
 Tells whether there is data to read in the pipeline.
sync_iter begin (void)
 These two iterators can be used into algorithm of std.
sync_iter end (void)
range_step_type build_range (size_t nbSteps, chunk_t aCM=chunk_t())
 Range creation is protected by a mutex, because its reads internal data.

Private Types

typedef pipebase< Container,
CondVar > 
pipebase_t

Private Member Functions

 GccNoFriend (private)
 GccNoFriend (private)
void slice_del (slice *slicePtr)
 Removes this slice from the list of slices being used by sub-threads.
 GccNoFriend (private)
void init (bool aFull)
void wait_for_writing (void)
 Used by push_back and append. The mutex must be locked.
void setup_rd_and_wr_iters (void)
 This must be done after insertions. Used by push_back and append.

Private Attributes

CondVar _condNotFull
 Can use any conditions as long as they are based on the same mutex.
GccNoFriend(private) iterator _it_wr
size_t _nbWaitWr
slice_slice_first
slice_slice_last

Friends

class range_step< pipe_circular< Container, CondVar >,pipe_circular< Container, CondVar > >
 This does not work with gcc 3.x.y. Find GccNoFriend.

Classes

class  reader
 Template param for pipe_itr, an iterator in pipelines'underlying container. More...
class  slice

Detailed Description

template<class Container, class CondVar>
class rpa::pipe_circular< Container, CondVar >

A circular buffer based on any kind of container.


Member Typedef Documentation

template<class Container, class CondVar>
typedef pipebase_t::iterator rpa::pipe_circular< Container, CondVar >::iterator

Reimplemented from rpa::pipebase< Container, CondVar >.

template<class Container, class CondVar>
typedef pipebase_t::mutex_type rpa::pipe_circular< Container, CondVar >::mutex_type

Reimplemented from rpa::pipebase< Container, CondVar >.

template<class Container, class CondVar>
typedef pipebase< Container, CondVar > rpa::pipe_circular< Container, CondVar >::pipebase_t [private]

template<class Container, class CondVar>
typedef range_step< pipe_circular, pipe_circular > rpa::pipe_circular< Container, CondVar >::range_step_type

This range can be used into any algorithm of this library. It is synchronized with the internal mutex of the container.

template<class Container, class CondVar>
typedef pipe_itr< value_type, reader > rpa::pipe_circular< Container, CondVar >::sync_iter

template<class Container, class CondVar>
typedef pipebase_t::value_type rpa::pipe_circular< Container, CondVar >::value_type


Constructor & Destructor Documentation

template<class Container, class CondVar>
rpa::pipe_circular< Container, CondVar >::pipe_circular ( mutex_type mtxPtr,
size_t  maxNb 
) [inline]

Sets the maximum size of the container. The buffer is not full at the beginning. We could do a lazy-resizing, only when it is necessary, but there is no point to wait : If a given size is necessary, why not resizing now ? More: By setting the right size immediately, we ensure that the iterators are always valid. On the other hand, the real shame of it is that we must always pay the price of a full allocation even for a couple of data. (This is also true for output buffers obuf_iterator). To compensate this, a buffer can be reused, once allocated.

template<class Container, class CondVar>
template<class Iter>
rpa::pipe_circular< Container, CondVar >::pipe_circular ( mutex_type mtxPtr,
Iter  begIter,
Iter  endIter,
bool  shutFlag = true 
) [inline]

Initialize the buffer with a content. At the beginning, the buffer is considered as full.

template<class Container, class CondVar>
rpa::pipe_circular< Container, CondVar >::pipe_circular ( mutex_type mtxPtr,
const Container &  aCont,
bool  shutFlag = true 
) [inline]

Initialize the buffer with a content. At the beginning, the buffer is considered as full.

template<class Container, class CondVar>
rpa::pipe_circular< Container, CondVar >::~pipe_circular (  )  [inline]

QUESTION: FOR WHICH REASON ALL WRITERS HAVE FINISHED ?


Member Function Documentation

template<class Container, class CondVar>
template<class IterIn>
void rpa::pipe_circular< Container, CondVar >::append ( IterIn  itBeg,
IterIn  itEnd,
size_t  szReserve 
) [inline]

Copies piece by piece, until the buffer is full, then waits until it gets read by other threads, then writes again. Uses most of the code of 'pipe_circularpush_back'.

Theoretically, it would be faster to wait until much space is freed: This would avoid many cond_wait. This is not possible in the general case: The most expensive is to go back to the kernel anyway.

Now we can copy as much element as we want until the writing iterator reaches the end of the buffer. We could specialize this copy if both types of iterators are random_access. The idea would be to count how many elements can be copied in one go, and then use std::copy_n.

We have inserted many elements, so we must notify reading threads:

template<class Container, class CondVar>
sync_iter rpa::pipe_circular< Container, CondVar >::begin ( void   )  [inline]

These two iterators can be used into algorithm of std.

Reimplemented from rpa::pipe_container< Container >.

template<class Container, class CondVar>
range_step_type rpa::pipe_circular< Container, CondVar >::build_range ( size_t  nbSteps,
chunk_t  aCM = chunk_t() 
) [inline]

Range creation is protected by a mutex, because its reads internal data.

template<class Container, class CondVar>
void rpa::pipe_circular< Container, CondVar >::check ( void   )  const [inline]

If Not rd_before_wr, then distance will never stops.

Casts to the base class, in order to use its check method.

Reimplemented from rpa::pipebase< Container, CondVar >.

template<class Container, class CondVar>
bool rpa::pipe_circular< Container, CondVar >::data_ready ( void   )  const [inline]

Tells whether there is data to read in the pipeline.

'full' means: (pipebase_t::_it_rd == _it_wr) && (false == _rd_before_wr) So, we add another check to avoid the ambiguity with emptiness.

template<class Container, class CondVar>
sync_iter rpa::pipe_circular< Container, CondVar >::end ( void   )  [inline]

Reimplemented from rpa::pipe_container< Container >.

template<class Container, class CondVar>
rpa::pipe_circular< Container, CondVar >::GccNoFriend ( private   )  [inline, private]

When a slice is just created with a 'chop', or is chopped again, the end of the slice becomes the 'Rd' of the slice, that is, the first place to read from. The mutex stays locked between the lock and this method. full = (pipebase_t::_it_rd == _it_wr) && (false == _rd_before_wr);

template<class Container, class CondVar>
rpa::pipe_circular< Container, CondVar >::GccNoFriend ( private   )  [inline, private]

template<class Container, class CondVar>
rpa::pipe_circular< Container, CondVar >::GccNoFriend ( private   )  [inline, private]

template<class Container, class CondVar>
void rpa::pipe_circular< Container, CondVar >::init ( bool  aFull  )  [inline, private]

The flag indicates whether the container is full at the beginning. The flag _rd_before_wr does not take the same value depending if the container is true or not. If the two iterators rd et wr are on the same position, if there is nothing in the container, rd_before_wr is true, otherwise false.

It points in fact at the end.

template<class Container, class CondVar>
void rpa::pipe_circular< Container, CondVar >::push_back ( const value_type aV  )  [inline]

This is compatible with std::back_inserter. If _slice_first is not NULL, it means that there is at least one slice which is currently used by a thread. If its beginning is at the place to write, we cannot change content which is being read now. On the other hand, the insertion itself cannot invalidate iterators because, in a circular buffer, all elements are already allocated.

This notifies only one thread because only one element is inserted.

template<class Container, class CondVar>
void rpa::pipe_circular< Container, CondVar >::setup_rd_and_wr_iters ( void   )  [inline, private]

This must be done after insertions. Used by push_back and append.

This is done even if _it_rd is at the beginning. Maybe the pipe is now full.

_rd cannot be before _wr except if they are at the same place. If this is so, and if the container is empty, then exceptionnaly set to false. This is because the information of full+before+(rd==wr) is redundant.

At this stage, the pipeline is OK.

template<class Container, class CondVar>
void rpa::pipe_circular< Container, CondVar >::slice_del ( slice slicePtr  )  [inline, private]

Removes this slice from the list of slices being used by sub-threads.

If this slice is the first of the list, it may be blocking writes if there is no more space. This must be guarded by the pipeline's mutex.

This tests first the presence at the beginning rather than the end, because there is a specific processing: If the slice begins at the writing position, then it must unblock threads which are waiting to write in the buffer.

Now the list is empty.

Maybe this slice is blocking some writing thread. We wake up all the threads which are waiting to write in the pipeline.

Just removing the slice from the list. After that, the list cannot be empty, otherwise _first == slicePtr (1st test).

template<class Container, class CondVar>
void rpa::pipe_circular< Container, CondVar >::wait_for_writing ( void   )  [inline, private]

Used by push_back and append. The mutex must be locked.

It returns when there is room to write new data.

A new thread is waiting to write.

If the pipe is full, it is impossible to write in it. If it is not full, but the first 'running' slice is sitting where we need to write data, we must wait too. The running slices are in a list sorted by order of creation, and therefore follows the order of writing and reading in the circular pipe.

The thread has finished to wait for writing.


Friends And Related Function Documentation

template<class Container, class CondVar>
friend class range_step< pipe_circular< Container, CondVar >,pipe_circular< Container, CondVar > > [friend]

This does not work with gcc 3.x.y. Find GccNoFriend.


Member Data Documentation

template<class Container, class CondVar>
CondVar rpa::pipe_circular< Container, CondVar >::_condNotFull [private]

Can use any conditions as long as they are based on the same mutex.

template<class Container, class CondVar>
GccNoFriend (private) iterator rpa::pipe_circular< Container, CondVar >::_it_wr [private]

This points on the next free place to write an element, or on the reading iterator if the pipeline is full. If it is full, both pointers are equal and the flag _rd_before is false.

template<class Container, class CondVar>
size_t rpa::pipe_circular< Container, CondVar >::_nbWaitWr [private]

This is the number of threads currently waiting to write data. It is protected by condNotFull and is used for notifying when more than one thread may be woken up, when a full slice is released. When freeing a single element (With a single read), only one thread is woken up.

template<class Container, class CondVar>
slice* rpa::pipe_circular< Container, CondVar >::_slice_first [private]

template<class Container, class CondVar>
slice * rpa::pipe_circular< Container, CondVar >::_slice_last [private]


The documentation for this class was generated from the following file:
Generated on Tue Sep 25 10:20:37 2007 for rpa by  doxygen 1.4.7