00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _RINGBUFFER_H_
00022 #define _RINGBUFFER_H_
00023
00024 #include <sys/types.h>
00025
00026 #include "system/System.h"
00027 #include "Scavenger.h"
00028
00029
00030
00031 #ifdef DEBUG_RINGBUFFER
00032 #include <iostream>
00033 #endif
00034
00044 template <typename T, int N = 1>
00045 class RingBuffer
00046 {
00047 public:
00057 RingBuffer(size_t n);
00058
00059 virtual ~RingBuffer();
00060
00065 size_t getSize() const;
00066
00072 void resize(size_t newSize);
00073
00078 bool mlock();
00079
00084 void reset();
00085
00090 size_t getReadSpace(int R = 0) const;
00091
00095 size_t getWriteSpace() const;
00096
00102 size_t read(T *destination, size_t n, int R = 0);
00103
00110 size_t readAdding(T *destination, size_t n, int R = 0);
00111
00119 T readOne(int R = 0);
00120
00128 size_t peek(T *destination, size_t n, int R = 0) const;
00129
00136 T peekOne(int R = 0) const;
00137
00144 size_t skip(size_t n, int R = 0);
00145
00151 size_t write(const T *source, size_t n);
00152
00158 size_t zero(size_t n);
00159
00160 protected:
00161 T *m_buffer;
00162 volatile size_t m_writer;
00163 volatile size_t m_readers[N];
00164 size_t m_size;
00165 bool m_mlocked;
00166
00167 static Scavenger<ScavengerArrayWrapper<T> > m_scavenger;
00168
00169 private:
00170 RingBuffer(const RingBuffer &);
00171 RingBuffer &operator=(const RingBuffer &);
00172 };
00173
00174 template <typename T, int N>
00175 Scavenger<ScavengerArrayWrapper<T> > RingBuffer<T, N>::m_scavenger;
00176
00177 template <typename T, int N>
00178 RingBuffer<T, N>::RingBuffer(size_t n) :
00179 m_buffer(new T[n + 1]),
00180 m_writer(0),
00181 m_size(n + 1),
00182 m_mlocked(false)
00183 {
00184 #ifdef DEBUG_RINGBUFFER
00185 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::RingBuffer(" << n << ")" << std::endl;
00186 #endif
00187
00188 for (int i = 0; i < N; ++i) m_readers[i] = 0;
00189
00190 m_scavenger.scavenge();
00191 }
00192
00193 template <typename T, int N>
00194 RingBuffer<T, N>::~RingBuffer()
00195 {
00196 #ifdef DEBUG_RINGBUFFER
00197 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::~RingBuffer" << std::endl;
00198 #endif
00199
00200 if (m_mlocked) {
00201 MUNLOCK((void *)m_buffer, m_size * sizeof(T));
00202 }
00203 delete[] m_buffer;
00204
00205 m_scavenger.scavenge();
00206 }
00207
00208 template <typename T, int N>
00209 size_t
00210 RingBuffer<T, N>::getSize() const
00211 {
00212 #ifdef DEBUG_RINGBUFFER
00213 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getSize(): " << m_size-1 << std::endl;
00214 #endif
00215
00216 return m_size - 1;
00217 }
00218
00219 template <typename T, int N>
00220 void
00221 RingBuffer<T, N>::resize(size_t newSize)
00222 {
00223 #ifdef DEBUG_RINGBUFFER
00224 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resize(" << newSize << ")" << std::endl;
00225 #endif
00226
00227 m_scavenger.scavenge();
00228
00229 if (m_mlocked) {
00230 MUNLOCK((void *)m_buffer, m_size * sizeof(T));
00231 }
00232
00233 m_scavenger.claim(new ScavengerArrayWrapper<T>(m_buffer));
00234
00235 reset();
00236 m_buffer = new T[newSize + 1];
00237 m_size = newSize + 1;
00238
00239 if (m_mlocked) {
00240 if (MLOCK((void *)m_buffer, m_size * sizeof(T))) {
00241 m_mlocked = false;
00242 }
00243 }
00244 }
00245
00246 template <typename T, int N>
00247 bool
00248 RingBuffer<T, N>::mlock()
00249 {
00250 if (MLOCK((void *)m_buffer, m_size * sizeof(T))) return false;
00251 m_mlocked = true;
00252 return true;
00253 }
00254
00255 template <typename T, int N>
00256 void
00257 RingBuffer<T, N>::reset()
00258 {
00259 #ifdef DEBUG_RINGBUFFER
00260 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::reset" << std::endl;
00261 #endif
00262
00263 m_writer = 0;
00264 for (int i = 0; i < N; ++i) m_readers[i] = 0;
00265 }
00266
00267 template <typename T, int N>
00268 size_t
00269 RingBuffer<T, N>::getReadSpace(int R) const
00270 {
00271 size_t writer = m_writer;
00272 size_t reader = m_readers[R];
00273 size_t space = 0;
00274
00275 if (writer > reader) space = writer - reader;
00276 else space = ((writer + m_size) - reader) % m_size;
00277
00278 #ifdef DEBUG_RINGBUFFER
00279 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getReadSpace(" << R << "): " << space << std::endl;
00280 #endif
00281
00282 return space;
00283 }
00284
00285 template <typename T, int N>
00286 size_t
00287 RingBuffer<T, N>::getWriteSpace() const
00288 {
00289 size_t space = 0;
00290 for (int i = 0; i < N; ++i) {
00291 size_t here = (m_readers[i] + m_size - m_writer - 1) % m_size;
00292 if (i == 0 || here < space) space = here;
00293 }
00294
00295 #ifdef DEBUG_RINGBUFFER
00296 size_t rs(getReadSpace()), rp(m_readers[0]);
00297
00298 std::cerr << "RingBuffer: write space " << space << ", read space "
00299 << rs << ", total " << (space + rs) << ", m_size " << m_size << std::endl;
00300 std::cerr << "RingBuffer: reader " << rp << ", writer " << m_writer << std::endl;
00301 #endif
00302
00303 #ifdef DEBUG_RINGBUFFER
00304 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getWriteSpace(): " << space << std::endl;
00305 #endif
00306
00307 return space;
00308 }
00309
00310 template <typename T, int N>
00311 size_t
00312 RingBuffer<T, N>::read(T *destination, size_t n, int R)
00313 {
00314 #ifdef DEBUG_RINGBUFFER
00315 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read(dest, " << n << ", " << R << ")" << std::endl;
00316 #endif
00317
00318 size_t available = getReadSpace(R);
00319 if (n > available) {
00320 #ifdef DEBUG_RINGBUFFER
00321 std::cerr << "WARNING: Only " << available << " samples available"
00322 << std::endl;
00323 #endif
00324 memset(destination + available, 0, (n - available) * sizeof(T));
00325 n = available;
00326 }
00327 if (n == 0) return n;
00328
00329 size_t here = m_size - m_readers[R];
00330 if (here >= n) {
00331 memcpy(destination, m_buffer + m_readers[R], n * sizeof(T));
00332 } else {
00333 memcpy(destination, m_buffer + m_readers[R], here * sizeof(T));
00334 memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
00335 }
00336
00337 m_readers[R] = (m_readers[R] + n) % m_size;
00338
00339 #ifdef DEBUG_RINGBUFFER
00340 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read: read " << n << ", reader now " << m_readers[R] << std::endl;
00341 #endif
00342
00343 return n;
00344 }
00345
00346 template <typename T, int N>
00347 size_t
00348 RingBuffer<T, N>::readAdding(T *destination, size_t n, int R)
00349 {
00350 #ifdef DEBUG_RINGBUFFER
00351 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readAdding(dest, " << n << ", " << R << ")" << std::endl;
00352 #endif
00353
00354 size_t available = getReadSpace(R);
00355 if (n > available) {
00356 #ifdef DEBUG_RINGBUFFER
00357 std::cerr << "WARNING: Only " << available << " samples available"
00358 << std::endl;
00359 #endif
00360 n = available;
00361 }
00362 if (n == 0) return n;
00363
00364 size_t here = m_size - m_readers[R];
00365
00366 if (here >= n) {
00367 for (size_t i = 0; i < n; ++i) {
00368 destination[i] += (m_buffer + m_readers[R])[i];
00369 }
00370 } else {
00371 for (size_t i = 0; i < here; ++i) {
00372 destination[i] += (m_buffer + m_readers[R])[i];
00373 }
00374 for (size_t i = 0; i < (n - here); ++i) {
00375 destination[i + here] += m_buffer[i];
00376 }
00377 }
00378
00379 m_readers[R] = (m_readers[R] + n) % m_size;
00380 return n;
00381 }
00382
00383 template <typename T, int N>
00384 T
00385 RingBuffer<T, N>::readOne(int R)
00386 {
00387 #ifdef DEBUG_RINGBUFFER
00388 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readOne(" << R << ")" << std::endl;
00389 #endif
00390
00391 if (m_writer == m_readers[R]) {
00392 #ifdef DEBUG_RINGBUFFER
00393 std::cerr << "WARNING: No sample available"
00394 << std::endl;
00395 #endif
00396 T t;
00397 memset(&t, 0, sizeof(T));
00398 return t;
00399 }
00400 T value = m_buffer[m_readers[R]];
00401 if (++m_readers[R] == m_size) m_readers[R] = 0;
00402 return value;
00403 }
00404
00405 template <typename T, int N>
00406 size_t
00407 RingBuffer<T, N>::peek(T *destination, size_t n, int R) const
00408 {
00409 #ifdef DEBUG_RINGBUFFER
00410 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(dest, " << n << ", " << R << ")" << std::endl;
00411 #endif
00412
00413 size_t available = getReadSpace(R);
00414 if (n > available) {
00415 #ifdef DEBUG_RINGBUFFER
00416 std::cerr << "WARNING: Only " << available << " samples available"
00417 << std::endl;
00418 #endif
00419 memset(destination + available, 0, (n - available) * sizeof(T));
00420 n = available;
00421 }
00422 if (n == 0) return n;
00423
00424 size_t here = m_size - m_readers[R];
00425 if (here >= n) {
00426 memcpy(destination, m_buffer + m_readers[R], n * sizeof(T));
00427 } else {
00428 memcpy(destination, m_buffer + m_readers[R], here * sizeof(T));
00429 memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
00430 }
00431
00432 #ifdef DEBUG_RINGBUFFER
00433 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek: read " << n << std::endl;
00434 #endif
00435
00436 return n;
00437 }
00438
00439 template <typename T, int N>
00440 T
00441 RingBuffer<T, N>::peekOne(int R) const
00442 {
00443 #ifdef DEBUG_RINGBUFFER
00444 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(" << R << ")" << std::endl;
00445 #endif
00446
00447 if (m_writer == m_readers[R]) {
00448 #ifdef DEBUG_RINGBUFFER
00449 std::cerr << "WARNING: No sample available"
00450 << std::endl;
00451 #endif
00452 T t;
00453 memset(&t, 0, sizeof(T));
00454 return t;
00455 }
00456 T value = m_buffer[m_readers[R]];
00457 return value;
00458 }
00459
00460 template <typename T, int N>
00461 size_t
00462 RingBuffer<T, N>::skip(size_t n, int R)
00463 {
00464 #ifdef DEBUG_RINGBUFFER
00465 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::skip(" << n << ", " << R << ")" << std::endl;
00466 #endif
00467
00468 size_t available = getReadSpace(R);
00469 if (n > available) {
00470 #ifdef DEBUG_RINGBUFFER
00471 std::cerr << "WARNING: Only " << available << " samples available"
00472 << std::endl;
00473 #endif
00474 n = available;
00475 }
00476 if (n == 0) return n;
00477 m_readers[R] = (m_readers[R] + n) % m_size;
00478 return n;
00479 }
00480
00481 template <typename T, int N>
00482 size_t
00483 RingBuffer<T, N>::write(const T *source, size_t n)
00484 {
00485 #ifdef DEBUG_RINGBUFFER
00486 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write(" << n << ")" << std::endl;
00487 #endif
00488
00489 size_t available = getWriteSpace();
00490 if (n > available) {
00491 #ifdef DEBUG_RINGBUFFER
00492 std::cerr << "WARNING: Only room for " << available << " samples"
00493 << std::endl;
00494 #endif
00495 n = available;
00496 }
00497 if (n == 0) return n;
00498
00499 size_t here = m_size - m_writer;
00500 if (here >= n) {
00501 memcpy(m_buffer + m_writer, source, n * sizeof(T));
00502 } else {
00503 memcpy(m_buffer + m_writer, source, here * sizeof(T));
00504 memcpy(m_buffer, source + here, (n - here) * sizeof(T));
00505 }
00506
00507 m_writer = (m_writer + n) % m_size;
00508
00509 #ifdef DEBUG_RINGBUFFER
00510 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write: wrote " << n << ", writer now " << m_writer << std::endl;
00511 #endif
00512
00513 return n;
00514 }
00515
00516 template <typename T, int N>
00517 size_t
00518 RingBuffer<T, N>::zero(size_t n)
00519 {
00520 #ifdef DEBUG_RINGBUFFER
00521 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::zero(" << n << ")" << std::endl;
00522 #endif
00523
00524 size_t available = getWriteSpace();
00525 if (n > available) {
00526 #ifdef DEBUG_RINGBUFFER
00527 std::cerr << "WARNING: Only room for " << available << " samples"
00528 << std::endl;
00529 #endif
00530 n = available;
00531 }
00532 if (n == 0) return n;
00533
00534 size_t here = m_size - m_writer;
00535 if (here >= n) {
00536 memset(m_buffer + m_writer, 0, n * sizeof(T));
00537 } else {
00538 memset(m_buffer + m_writer, 0, here * sizeof(T));
00539 memset(m_buffer, 0, (n - here) * sizeof(T));
00540 }
00541
00542 m_writer = (m_writer + n) % m_size;
00543 return n;
00544 }
00545
00546 #endif // _RINGBUFFER_H_