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

ringbuffer.hh

00001 /*
00002  * PIAVE - PIAVE Is A Video Editor
00003  *
00004  * Copyright (C) 2002 Rolf Dubitzky, rolf@dubitzky.de
00005  *
00006  */
00007 
00008 /*
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software Foundation,
00021  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00022  */
00023 
00024 #if ! defined ( RINGBUFFER_HH )
00025 #define RINGBUFFER_HH
00026 
00027 namespace PIAVE {
00028 
00029     /*
00030      * \class RingBuffer implements a simple ringbuffer with pointers
00031      *
00032      */
00033     template< class V >
00034     class PtrRingBuffer
00035     {
00036       public:
00037         PtrRingBuffer( size_t s = 128 );
00038         ~PtrRingBuffer();
00039 
00040         void push( const V * v );
00041         const V * pop();
00042         int remove( const V * v );
00043         bool isEmpty() const { return _head==_tail; }
00044         bool isFull() const { int h=_head; inc(h); return h==_tail; }
00045 
00046       private:
00047         void inc( int & i ) const { if ( ++i == _size ) i = 0; }
00048 
00049       private:
00050         const V ** _buffer;
00051         int _head;
00052         int _tail;
00053         int _size;
00054     };
00055 
00056     template< class V >
00057     PtrRingBuffer<V>::PtrRingBuffer( size_t s ) :
00058       _buffer( new const V*[s] ),
00059       _head( 0 ),
00060       _tail( 0 ),
00061       _size( s )
00062     {
00063     }
00064 
00065     template< class V >
00066     PtrRingBuffer<V>::~PtrRingBuffer()
00067     {
00068         if ( _buffer ) delete [] _buffer;
00069     }
00070 
00071     template< class V >
00072     void
00073     PtrRingBuffer<V>::push( const V * v )
00074     {
00075         if ( isFull() ) {
00076 //            WARN( "Buffer is full - dropping cmnd" );
00077         } else {
00078             _buffer[ _head ] = v;
00079             inc( _head );
00080         }
00081         
00082         return;
00083     }
00084     
00085     template< class V >
00086     const V *
00087     PtrRingBuffer<V>::pop()
00088     {
00089         /* suppress zores */
00090         while ( _buffer[ _tail ] == 0 &&
00091                 _tail != _head )
00092         {
00093             inc( _tail );
00094         }
00095 
00096         /* if we have something left, return it */
00097         if ( isEmpty() ) return 0;
00098 
00099         const V * ret = _buffer[ _tail ];
00100         _buffer[ _tail ] = 0;
00101 
00102         inc( _tail );
00103 
00104         return ret;
00105     }
00106 
00107     template< class V >
00108     int
00109     PtrRingBuffer<V>::remove( const V * v )
00110     {
00111         if ( isEmpty() ) return 0;
00112         int n = 0;
00113         for ( int i=_tail; i!=_head; inc(i) )
00114         {
00115             if ( _buffer[ i ] != 0 ) {
00116                 if ( *_buffer[ i ] == *v ) {
00117                     delete _buffer[ i ];
00118                     _buffer[ i ] = 0;
00119                     n++;
00120                 }
00121             }
00122         }
00123         return n;
00124     }    
00125 
00126 
00127 
00128     /*
00129      * \class ValRingBuffer implements a simple ringbuffer with values
00130      * FIXME 
00131      *     this is just a copy and paste short term solution the
00132      *     PtrRingBuffer uses dereferencing comparison for remove,
00133      *     which is not possible for values. Also PtrRB suppresses
00134      *     zeroes. So putting V* into a ValRB is somethng elsethan
00135      *     putting V into a PtrRB....  this is ugly and should be
00136      *     replaced by something better.
00137      */
00138     template< class V >
00139     class ValRingBuffer
00140     {
00141       public:
00142         ValRingBuffer( size_t s = 128 );
00143         ~ValRingBuffer();
00144 
00145         void push( const V v );
00146         const V pop();
00147         bool isEmpty() const { return _head==_tail; }
00148         bool isFull() const { int h=_head; inc(h); return h==_tail; }
00149 
00150         int getCurSize() const;
00151         int getN( int n, V * dest );
00152         int putN( int n, V * src );
00153         void clean() { _tail = _head; }
00154 
00155       private:
00156         void inc( int & i ) const { if ( ++i == _size ) i = 0; }
00157 
00158       private:
00159         V * _buffer;
00160         int _head;
00161         int _tail;
00162         int _size;
00163     };
00164 
00165     template< class V >
00166     ValRingBuffer<V>::ValRingBuffer( size_t s ) :
00167       _buffer( new V[s] ),
00168       _head( 0 ),
00169       _tail( 0 ),
00170       _size( s )
00171     {
00172     }
00173 
00174     template< class V >
00175     ValRingBuffer<V>::~ValRingBuffer()
00176     {
00177         if ( _buffer ) delete [] _buffer;
00178     }
00179 
00180     template< class V >
00181     void
00182     ValRingBuffer<V>::push( const V v )
00183     {
00184         if ( isFull() ) {
00185 //            WARN( "Buffer is full - dropping cmnd" );
00186         } else {
00187             _buffer[ _head ] = v;
00188             inc( _head );
00189         }
00190         
00191         return;
00192     }
00193     
00194     template< class V >
00195     const V
00196     ValRingBuffer<V>::pop()
00197     {
00198         /* if we have something left, return it */
00199         if ( isEmpty() ) return 0;
00200 
00201         const V ret = _buffer[ _tail ];
00202         _buffer[ _tail ] = 0;
00203 
00204         inc( _tail );
00205 
00206         return ret;
00207     }
00208 
00209     template< class V >
00210     int 
00211     ValRingBuffer<V>::getCurSize() const
00212     {
00213         /* wrap */
00214         if (_tail>_head) return _size-_tail+_head;
00215 
00216         /* no wrap */
00217         return _head-_tail;
00218     }
00219     
00220     template< class V >
00221     int 
00222     ValRingBuffer<V>::getN( int n, V * dest )
00223     {
00224         int nCopied = 0;
00225 
00226 //        INFO( PRINTV(_head)<<PRINTV(_tail));
00227         /* empty */
00228         if (_tail==_head) return 0;
00229 
00230         /* wrap */
00231         if (_tail>_head) 
00232         {
00233             int tail_chunk = _size-_tail;
00234             if ( n>tail_chunk )
00235             {
00236                 memcpy( dest, _buffer+_tail, tail_chunk*sizeof(V) );
00237                 nCopied = tail_chunk;
00238                 int rest = 0;
00239                 if ( n-tail_chunk<=_head)
00240                 {
00241                     rest = n-tail_chunk;
00242                     _tail = rest;
00243                 } else {
00244                     rest = _head;
00245                     _tail = _head;
00246                 }
00247                 memcpy( dest+tail_chunk, _buffer, rest*sizeof(V) );
00248                 nCopied += rest;
00249             } else {
00250                 memcpy( dest, _buffer+_tail, n*sizeof(V) );
00251                 nCopied = n;
00252                 _tail+=n;
00253                 if ( _tail==_size ) _tail = 0;
00254             }
00255 //        INFO( PRINTV(_head)<<PRINTV(_tail));
00256             return nCopied;
00257         }
00258         
00259         /* no wrap */
00260         int size     = _head-_tail;
00261         int old_tail = _tail;
00262         if ( n>size )
00263         {
00264             nCopied = size;
00265             _tail = _head;
00266         } else {
00267             nCopied = n;
00268             _tail+=n;
00269         }
00270         memcpy( dest, _buffer+old_tail, nCopied*sizeof(V) );
00271 //        INFO( PRINTV(_head)<<PRINTV(_tail));
00272         if ( _tail==_size ) _tail = 0;
00273         return nCopied;
00274     }
00275 
00276     template< class V >
00277     int 
00278     ValRingBuffer<V>::putN( int n, V * src )
00279     {
00280         int curSize = getCurSize();
00281         int free = _size-curSize-1;
00282 
00283         /* full */
00284         if ( n>free ) return 0;
00285 
00286 //        INFO( PRINTV(_head)<<PRINTV(_tail));
00287 
00288         /* wrap */
00289         int head_chunk = _size-_head;
00290         if ( n>head_chunk ) 
00291         {
00292             memcpy( _buffer+_head, src, head_chunk*sizeof(V) );
00293             memcpy( _buffer, src+head_chunk, (n-head_chunk)*sizeof(V) );
00294             _head = n-head_chunk;
00295             if ( _head==_size ) _head=0;
00296 //            INFO( PRINTV(_head)<<PRINTV(_tail));
00297             return n;
00298         }
00299         
00300         /* no wrap */
00301         memcpy( _buffer+_head, src, n*sizeof(V) );
00302         _head += n;
00303         if ( _head==_size ) _head=0;
00304 //        INFO( PRINTV(_head)<<PRINTV(_tail));
00305 
00306         return n;
00307     }
00308 
00309 }
00310     
00311 #endif

Generated on Tue Oct 14 20:45:37 2003 for piave by doxygen1.2.18