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

circularbuffer.h

Go to the documentation of this file.
00001 /*  circularbuffer.h - N producers/consumers circular buffer
00002     Copyright (C) 2001-2004 Mark Weaver
00003     Written by Mark Weaver <mark@npsl.co.uk>
00004 
00005     Part of the Open-Win32 library.
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library 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 GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public
00017     License along with this library; if not, write to the
00018     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019     Boston, MA  02111-1307, USA.
00020 */
00021 
00022 #ifndef OW32_circularbuffer_h
00023 #define OW32_circularbuffer_h
00024 
00025 #include <OW32/SyncObjects.h>
00026 #include <cstddef> // for size_t
00027 
00033 namespace OW32
00034 {
00035 
00037 template <class T>
00038 class CCircularBuffer
00039 {
00040 public:
00053     CCircularBuffer(size_t queueSize) :
00054         m_head(0),
00055         m_tail(0),
00056         m_semEmpty(static_cast<LONG>(queueSize), static_cast<LONG>(queueSize)),
00057         m_semFull(static_cast<LONG>(queueSize), 0L),
00058         m_evBreak(TRUE),
00059         m_fBreak(false),
00060         m_queueSize(queueSize)
00061     {
00062         m_buf = new T[m_queueSize];
00063     }
00064 
00066     ~CCircularBuffer()
00067     {
00068         delete [] m_buf;
00069     }
00070 
00072     bool isBroken()
00073     {
00074         return m_fBreak;
00075     }
00076 
00085     void Break()
00086     {
00087         m_fBreak = true;
00088         m_evBreak.Set();
00089     }
00090 
00096     void ResetBreak()
00097     {
00098         m_fBreak = false;
00099         m_evBreak.Reset();
00100     }
00101 
00111     bool putElement(const T& el, DWORD nTimeout = INFINITE)
00112     {
00113         /* wait for a space */
00114         HANDLE wait_space[2] = { m_semEmpty, m_evBreak };
00115         
00116         switch (WaitForMultipleObjects(2, wait_space, FALSE, nTimeout)) {
00117         case WAIT_OBJECT_0:
00118             if (m_fBreak)
00119                 return false;
00120             break;
00121         case WAIT_TIMEOUT:
00122             return false;
00123         default:
00124             return false;
00125         }
00126 
00127         /* put the element, with protection for the tail */
00128         {
00129             CSingleLock access_tail(m_csTail);
00130             m_buf[m_tail] = el;
00131             m_tail = (m_tail+1)%m_queueSize;
00132         }
00133 
00134         /* release one waiting consumer */
00135         m_semFull.Release(1);
00136         return true;
00137     }
00138 
00148     bool getElement(T& el, DWORD nTimeout = INFINITE)
00149     {
00150         /* wait for an element */
00151         HANDLE wait_space[2] = { m_semFull, m_evBreak };
00152 
00153         switch (WaitForMultipleObjects(2, wait_space, FALSE, nTimeout)) {
00154         case WAIT_OBJECT_0:
00155             if (m_fBreak)
00156                 return false;
00157             break;
00158         case WAIT_TIMEOUT:
00159             return false;
00160         default:
00161             return false;
00162         }
00163 
00164         /* get the element, with protection for the head */
00165         {
00166             CSingleLock access_head(m_csHead);
00167             el = m_buf[m_head];
00168             m_head = (m_head+1)%m_queueSize;
00169         }
00170 
00171         /* release one waiting producer */
00172         m_semEmpty.Release(1);
00173         return true;
00174     }
00175 
00176 private:
00177     size_t              m_head, m_tail, m_queueSize;
00178     T*                  m_buf;
00179     CSemaphore          m_semEmpty, m_semFull;
00180     CCriticalSection    m_csHead, m_csTail;
00181 
00182     // event and predicate for aborting waiters
00183     CEvent              m_evBreak;
00184     bool                m_fBreak;
00185 
00186     // no copy or assign
00187     CCircularBuffer& operator=(const CCircularBuffer&);
00188     CCircularBuffer(const CCircularBuffer&);
00189 
00190 };
00191 
00192 }; // namespace OW32
00193 
00194 #endif // OW32_circularbuffer_h

Generated on Sun Jun 5 01:29:17 2005 for OW32 by  doxygen 1.3.9.1