![]() |
Mixxx
|
00001 #ifndef CIRCULARBUFFER_H 00002 #define CIRCULARBUFFER_H 00003 00004 #include <stdlib.h> 00005 00006 // CircularBuffer is a basic implementation of a constant-length circular 00007 // buffer. 00008 // 00009 // WARNING: CircularBuffer IS NOT THREAD SAFE! It is "sort of" thread safe on 00010 // platforms with atomic writes and aligned memory locations, but it is most 00011 // definitely not safe on x86 without memory barriers that could re-order reads 00012 // and writes. 00013 template <typename T> 00014 class CircularBuffer { 00015 public: 00016 CircularBuffer(unsigned int iLength) 00017 : m_iLength(iLength), 00018 m_pBuffer(new T[m_iLength]), 00019 m_iWritePos(0), 00020 m_iReadPos(0) { 00021 // No need to clear the buffer because we consider it to be empty right 00022 // now. 00023 } 00024 00025 virtual ~CircularBuffer() { 00026 delete [] m_pBuffer; 00027 m_pBuffer = NULL; 00028 } 00029 00030 // Returns true if the buffer is full 00031 inline bool isFull() const { 00032 return (m_iWritePos + 1) % m_iLength == m_iReadPos; 00033 } 00034 00035 // Returns true if the buffer is empty. 00036 inline bool isEmpty() const { 00037 return m_iReadPos == m_iWritePos; 00038 } 00039 00040 inline void clear() { 00041 m_iReadPos = 0; 00042 m_iWritePos = 0; 00043 } 00044 00045 // Returns the total capacity of the CircularBuffer in units of T 00046 inline unsigned int length() const { 00047 return m_iLength; 00048 } 00049 00050 // Write numItems into the CircularBuffer. Returns the total number of 00051 // items written, which could be less than numItems if the buffer becomes 00052 // full. 00053 unsigned int write(const T* pBuffer, const unsigned int numItems) { 00054 if (m_pBuffer == NULL) 00055 return 0; 00056 00057 unsigned int itemsWritten = 0; 00058 while (!isFull() && itemsWritten < numItems) { 00059 m_pBuffer[m_iWritePos++] = pBuffer[itemsWritten++]; 00060 m_iWritePos %= m_iLength; 00061 } 00062 return itemsWritten; 00063 } 00064 00065 // Read itemsToRead into pBuffer. Returns the total number of items read, 00066 // which may be less than itemsToRead if the buffer becomes empty. 00067 unsigned int read(T* pBuffer, const unsigned int itemsToRead) { 00068 if (m_pBuffer == NULL) 00069 return 0; 00070 00071 unsigned int itemsRead = 0; 00072 while (!isEmpty() && itemsRead < itemsToRead) { 00073 pBuffer[itemsRead++] = m_pBuffer[m_iReadPos++]; 00074 m_iReadPos %= m_iLength; 00075 } 00076 return itemsRead; 00077 } 00078 00079 unsigned int skip(const unsigned int itemsToRead) { 00080 if (m_pBuffer == NULL) 00081 return 0; 00082 unsigned int itemsRead = 0; 00083 while (!isEmpty() && itemsRead < itemsToRead) { 00084 m_iReadPos = (m_iReadPos + 1) % m_iLength; 00085 itemsRead++; 00086 } 00087 return itemsRead; 00088 } 00089 00090 private: 00091 const unsigned int m_iLength; 00092 T* m_pBuffer; 00093 unsigned int m_iWritePos; 00094 unsigned int m_iReadPos; 00095 }; 00096 00097 #endif /* CIRCULARBUFFER_H */