MNE-CPP  0.1.9
A Framework for Electrophysiology
circularbuffer.h
Go to the documentation of this file.
1 //=============================================================================================================
36 #ifndef CIRCULARBUFFER_H
37 #define CIRCULARBUFFER_H
38 
39 //=============================================================================================================
40 // INCLUDES
41 //=============================================================================================================
42 
43 #include "../utils_global.h"
44 
45 //=============================================================================================================
46 // QT INCLUDES
47 //=============================================================================================================
48 
49 #include <QPair>
50 #include <QSemaphore>
51 #include <QSharedPointer>
52 
53 //=============================================================================================================
54 // EIGEN INCLUDES
55 //=============================================================================================================
56 
57 #include <Eigen/Core>
58 
59 //=============================================================================================================
60 // DEFINE NAMESPACE UTILSLIB
61 //=============================================================================================================
62 
63 namespace UTILSLIB
64 {
65 
66 //=============================================================================================================
72 template<typename _Tp>
74 {
75 public:
76  typedef QSharedPointer<CircularBuffer> SPtr;
77  typedef QSharedPointer<const CircularBuffer> ConstSPtr;
79  //=========================================================================================================
85  explicit CircularBuffer(unsigned int uiMaxNumElements);
86 
87  //=========================================================================================================
92 
93  //=========================================================================================================
100  inline bool push(const _Tp* pArray, unsigned int size);
101 
102  //=========================================================================================================
108  inline bool push(const _Tp& newElement);
109 
110  //=========================================================================================================
116  inline bool pop(_Tp& element);
117 
118  //=========================================================================================================
122  void clear();
123 
124  //=========================================================================================================
128  inline void pause(bool);
129 
130  //=========================================================================================================
134  inline int getFreeElementsRead();
135 
136  //=========================================================================================================
140  inline int getFreeElementsWrite();
141 
142 private:
143  //=========================================================================================================
150  inline unsigned int mapIndex(int& index);
151  unsigned int m_uiMaxNumElements;
152  _Tp* m_pBuffer;
153  int m_iCurrentReadIndex;
154  int m_iCurrentWriteIndex;
155  QSemaphore* m_pFreeElements;
156  QSemaphore* m_pUsedElements;
157  int m_iTimeout;
159  bool m_bPause;
160 };
161 
162 //=============================================================================================================
163 // DEFINE MEMBER METHODS
164 //=============================================================================================================
165 
166 template<typename _Tp>
167 CircularBuffer<_Tp>::CircularBuffer(unsigned int uiMaxNumElements)
168 : m_uiMaxNumElements(uiMaxNumElements)
169 , m_pBuffer(new _Tp[m_uiMaxNumElements])
170 , m_iCurrentReadIndex(-1)
171 , m_iCurrentWriteIndex(-1)
172 , m_pFreeElements(new QSemaphore(m_uiMaxNumElements))
173 , m_pUsedElements(new QSemaphore(0))
174 , m_iTimeout(1000)
175 , m_bPause(false)
176 {
177 }
178 
179 //=============================================================================================================
180 
181 template<typename _Tp>
183 {
184  delete m_pFreeElements;
185  delete m_pUsedElements;
186  delete [] m_pBuffer;
187 }
188 
189 //=============================================================================================================
190 
191 template<typename _Tp>
192 inline bool CircularBuffer<_Tp>::push(const _Tp* pArray, unsigned int size)
193 {
194  if(!m_bPause) {
195  if(m_pFreeElements->tryAcquire(size, m_iTimeout)) {
196  for(unsigned int i = 0; i < size; ++i) {
197  m_pBuffer[mapIndex(m_iCurrentWriteIndex)] = pArray[i];
198  }
199  const QSemaphoreReleaser releaser(m_pUsedElements, size);
200  } else {
201  return false;
202  }
203  }
204 
205  return true;
206 }
207 
208 //=============================================================================================================
209 
210 template<typename _Tp>
211 inline bool CircularBuffer<_Tp>::push(const _Tp& newElement)
212 {
213  if(m_pFreeElements->tryAcquire(1, m_iTimeout)) {
214  m_pBuffer[mapIndex(m_iCurrentWriteIndex)] = newElement;
215  const QSemaphoreReleaser releaser(m_pUsedElements, 1);
216  } else {
217  return false;
218  }
219 
220  return true;
221 }
222 
223 //=============================================================================================================
224 
225 template<typename _Tp>
226 inline bool CircularBuffer<_Tp>::pop(_Tp& element)
227 {
228  if(!m_bPause) {
229  if(m_pUsedElements->tryAcquire(1, m_iTimeout)) {
230  element = m_pBuffer[mapIndex(m_iCurrentReadIndex)];
231  const QSemaphoreReleaser releaser(m_pFreeElements, 1);
232  } else {
233  return false;
234  }
235  }
236 
237  return true;
238 }
239 
240 //=============================================================================================================
241 
242 template<typename _Tp>
243 inline unsigned int CircularBuffer<_Tp>::mapIndex(int& index)
244 {
245  int aux = index;
246  return index = ++aux % m_uiMaxNumElements;
247 }
248 
249 //=============================================================================================================
250 
251 template<typename _Tp>
253 {
254  delete m_pFreeElements;
255  m_pFreeElements = new QSemaphore(m_uiMaxNumElements);
256  delete m_pUsedElements;
257  m_pUsedElements = new QSemaphore(0);
258 
259  m_iCurrentReadIndex = -1;
260  m_iCurrentWriteIndex = -1;
261 }
262 
263 //=============================================================================================================
264 
265 template<typename _Tp>
266 inline void CircularBuffer<_Tp>::pause(bool bPause)
267 {
268  m_bPause = bPause;
269 }
270 
271 //=============================================================================================================
272 
273 template<typename _Tp>
275 {
276  return m_pUsedElements->available();
277 }
278 
279 //=============================================================================================================
280 
281 template<typename _Tp>
283 {
284  return m_pFreeElements->available();
285 }
286 
287 //=============================================================================================================
288 // TYPEDEF
289 //=============================================================================================================
290 
300 } // NAMESPACE
301 
302 #endif // CIRCULARBUFFER_H
bool pop(_Tp &element)
The TEMPLATE CIRCULAR BUFFER provides a template for thread safe circular buffers.
QSharedPointer< CircularBuffer > SPtr
bool push(const _Tp *pArray, unsigned int size)
QSharedPointer< const CircularBuffer > ConstSPtr
CircularBuffer(unsigned int uiMaxNumElements)