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

wefts_ringbuffer.h

Go to the documentation of this file.
00001 /*
00002    wefts_ringbuffer.h
00003    Ringbuffer sync object
00004 
00005    $Id: wefts_ringbuffer.h,v 1.1 2003/08/17 01:15:19 jonnymind Exp $
00006 ---------------------------------------------
00007    Begin      : 2003-08-16 21:25
00008    Author     : Giancarlo Niccolai
00009 
00010    Last modified because:
00011 
00012 */
00013 
00014 /**************************************************************************
00015 *   This program is free software; you can redistribute it and/or modify  *
00016 *   it under the terms of the GNU Library General Public License as       *
00017 *   published by the Free Software Foundation; either version 2.1 of the  *
00018 *   License, or (at your option) any later version.                       *
00019 ***************************************************************************/
00020 
00021 #ifndef WT_RINGBUFFER_H
00022 #define WT_RINGBUFFER_H
00023 
00024 #include <wefts_mutex.h>
00025 #include <wefts_cond.h>
00026 #include <wefts_cleanup.h>
00027 #include <iostream>
00028 
00029 namespace Wefts {
00030 
00095 template < typename _T >
00096 class RingBuffer: public CleanupHandler
00097 {
00098 private:
00099    Mutex m_mutex;
00100    Condition m_rCond;
00101    Condition m_wCond;
00102 
00104    _T *m_buffer;
00105 
00107    unsigned long m_size;
00108 
00110    unsigned long m_wPos;
00112    unsigned long m_rPos;
00113 
00115    int m_wWaiting;
00117    int m_rWaiting;
00118 
00124    bool empty() const {
00125       return ( m_wPos == m_rPos + 1||
00126          (m_size > 1 &&m_wPos == 0 && m_rPos == m_size-1) );
00127    }
00128 
00134    bool full() const {
00135       return (m_wPos == m_rPos);
00136    }
00137 
00143    void put( _T data ) {
00144 
00145       bool was_empty = empty();
00146       if ( m_size == 1 ) {
00147          *m_buffer = data;
00148          m_wPos = 0;
00149       }
00150       else {
00151          m_buffer[ m_wPos ++ ] = data;
00152          if ( m_wPos == m_size ) m_wPos = 0;
00153       }
00154 
00155       if( was_empty && m_rWaiting != 0 )
00156          m_rCond.signal(); // tell the readers situation has changed.
00157    }
00158 
00159 
00164    _T get() {
00165       bool was_full = full();
00166 
00167       if ( m_rPos == m_size -1)
00168          m_rPos = 0;
00169       else
00170          m_rPos++;
00171 
00172       if( was_full && m_wWaiting != 0 ) {
00173          m_wCond.signal();
00174       }
00175       if ( m_size == 1 ) m_wPos = 1;
00176 
00177       return m_buffer[ m_rPos ];
00178    }
00179 
00180 
00181 public:
00182 
00189    RingBuffer ( const unsigned long size ) throw( InitError )
00190    {
00191       if ( size == 0 ) throw InitError();
00192       m_buffer = new _T[ size ];
00193       if ( m_buffer == 0 ) throw InitError();
00194 
00195       m_size = size;
00196 
00197       m_wPos = 1;
00198       m_rPos = 0;
00199       m_wWaiting = 0;
00200       m_rWaiting = 0;
00201 
00202       m_wCond.setMutex( &m_mutex );
00203       m_rCond.setMutex( &m_mutex );
00204 
00205       m_wCond.onStop( this, 0 ); // 0 == cleanup a writer
00206       m_rCond.onStop( this, 1 ); // 1 == cleanup a reader
00207    }
00208 
00209    ~RingBuffer() { delete m_buffer; }
00210 
00212    unsigned long size() const { m_size; }
00213 
00225    unsigned long free() {
00226       unsigned long ret;
00227 
00228       m_mutex.lock();
00229       if ( m_wPos > m_rPos )
00230          m_ret = m_size -m_wPos + m_rPos + 1;
00231       else
00232          m_ret = m_rPos - m_wPos;
00233       m_mutex.unlock();
00234 
00235       return ret;
00236    }
00237 
00239    void write( _T data )
00240    {
00241       m_mutex.lock();
00242 
00243       // have we to wait?
00244       if( full() ) {
00245          m_wWaiting++;
00246          while ( full() ) {
00247             m_wCond.wait();
00248          }
00249          m_wWaiting--;
00250       }
00251       put( data );
00252 
00253       m_mutex.unlock();
00254    }
00255 
00256    /* Waits until some data may be read and returns the read data. */
00257    _T read()
00258    {
00259       m_mutex.lock();
00260 
00261       // have we to wait?
00262       if( empty() ) {
00263          m_rWaiting++;
00264          while ( empty() ) {
00265             m_rCond.wait();
00266          }
00267          m_rWaiting--;
00268       }
00269       _T data = get();
00270       m_mutex.unlock();
00271       return data;
00272    }
00273 
00274 
00278    bool tryWrite( _T data ) {
00279       bool ret;
00280 
00281       m_mutex.lock();
00282       if ( ! full() ) {
00283          put( data );
00284          ret = true;
00285       }
00286       else
00287          ret = false;
00288       m_mutex.unlock();
00289 
00290       return ret;
00291    }
00292 
00298    bool tryRead( _T &data ) {
00299       bool ret;
00300 
00301       m_mutex.lock();
00302       if ( ! empty() ) {
00303          data = get();
00304          ret = true;
00305       }
00306       else
00307          ret = false;
00308       m_mutex.unlock();
00309 
00310       return ret;
00311    }
00312 
00314    void handleCleanup( int pos )
00315    {
00316       if ( pos == 0 ) // cleanup a writer
00317          m_wWaiting--;
00318       else
00319          m_rWaiting--;
00320 
00321       m_mutex.unlock();
00322    }
00323 };
00324 
00325 }
00326 #endif
00327 
00328 /* end wefts_ringbuffer.h */

Generated on Mon Dec 22 04:12:30 2003 for Wefts by doxygen1.2.18