Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

RingBuffer.hh

Go to the documentation of this file.
00001 /*
00002 
00003     Lockless ring buffer
00004     Copyright (C) 2004 Jussi Laako
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 */
00021 
00022 
00023 #include <cstdio>
00024 
00025 #include <Exception.hh>
00026 
00027 #include "dsp/DSPOp.hh"
00028 
00029 
00030 #ifndef RINGBUFFER_HH
00031     #define RINGBUFFER_HH
00032 
00033 
00037     class clXRingBuffer : public clException
00038     {
00039         public:
00040             clXRingBuffer (const char *cpErrorMsg) : 
00041                 clException(cpErrorMsg)
00042                 { }
00043     };
00044 
00045 
00049     template <class TRingBuffer_t> class clRingBuffer
00050     {
00051             volatile long lSize;
00052             volatile long lCount;
00053             volatile long lPutIndex;
00054             volatile long lGetIndex;
00055             clDSPAlloc Buffer;
00056         public:
00057             clRingBuffer ()
00058                 {
00059                     lSize = 0;
00060                     lCount = 0;
00061                     lPutIndex = 0;
00062                     lGetIndex = 0;
00063                 }
00064             clRingBuffer (const clRingBuffer<TRingBuffer_t> &CopySrc)
00065                 {
00066                     lSize = CopySrc.lSize;
00067                     lCount = CopySrc.lCount;
00068                     lPutIndex = CopySrc.lPutIndex;
00069                     lGetIndex = CopySrc.lGetIndex;
00070                     Buffer = CopySrc.Buffer;
00071                 }
00072             clRingBuffer (long lNewSize)
00073                 { SetSize(lNewSize); }
00074             void SetSize (long lNewSize)
00075                 {
00076                     Buffer.Size(lNewSize * sizeof(TRingBuffer_t));
00077                     lSize = lNewSize;
00078                     lCount = 0;
00079                     lPutIndex = 0;
00080                     lGetIndex = 0;
00081                 }
00082             void Lock ()
00083                 { Buffer.Lock(); }
00084             void UnLock ()
00085                 { Buffer.UnLock(); }
00086             long Size () const
00087                 {
00088                     return lSize;
00089                 }
00090             long GetCount () const
00091                 {
00092                     return lCount;
00093                 }
00094             void Put (const TRingBuffer_t *Src, long lSrcCount)
00095                 {
00096                     register long lLPutIdx = lPutIndex;
00097                     register long lLSize = lSize;
00098                     if (lSrcCount > lLSize)
00099                         throw clXRingBuffer("clRingBuffer::Put(): lSrcCount > lSize");
00100                     register long lTailSize = lLSize - lLPutIdx;
00101                     register long lHeadSize = lSrcCount - lTailSize;
00102                     TRingBuffer_t *LBuf = Buffer;
00103                     if (lHeadSize > 0)
00104                     {
00105                         clDSPOp::Copy(LBuf + lLPutIdx, Src, lTailSize);
00106                         clDSPOp::Copy(LBuf, Src + lTailSize, lHeadSize);
00107                     }
00108                     else
00109                     {
00110                         clDSPOp::Copy(LBuf + lLPutIdx, Src, lSrcCount);
00111                     }
00112                     lLPutIdx = (lLPutIdx + lSrcCount) % lLSize;
00113                     lPutIndex = lLPutIdx;
00114                     register long lLCount = lCount;
00115                     lLCount = (lLCount + lSrcCount) % lLSize;
00116                     lCount = lLCount;
00117                 }
00118             bool Get (TRingBuffer_t *Dst, long lDstCount)
00119                 {
00120                     register long lLCount = lCount;
00121                     if (lLCount < lDstCount)
00122                         return false;
00123                     lLCount -= lDstCount;
00124                     lCount = lLCount;
00125                     register long lLGetIdx = lGetIndex;
00126                     register long lLSize = lSize;
00127                     if (lDstCount > lLSize)
00128                         throw clXRingBuffer("clRingBuffer::Get(): lDstCount > lSize");
00129                     register long lTailSize = lLSize - lLGetIdx;
00130                     register long lHeadSize = lDstCount - lTailSize;
00131                     register long lNewIdx = (lLGetIdx + lDstCount) % lLSize;
00132                     lGetIndex = lNewIdx;
00133                     TRingBuffer_t *LBuf = Buffer;
00134                     if (lHeadSize > 0)
00135                     {
00136                         clDSPOp::Copy(Dst, LBuf + lLGetIdx, lTailSize);
00137                         clDSPOp::Copy(Dst + lTailSize, LBuf, lHeadSize);
00138                     }
00139                     else
00140                     {
00141                         clDSPOp::Copy(Dst, LBuf + lLGetIdx, lTailSize);
00142                     }
00143                     return true;
00144                 }
00145     };
00146 
00147 #endif

Generated on Sun Nov 7 14:32:00 2004 for libDSP by doxygen 1.3.6