annotate base/RingBuffer.h @ 875:3e6ed8a8577b tonioni

Use a sparse time-value model only for outputs with fixed bin count of 1, not for those with unknown bin count. (Precursor to using more than one model for outputs with unknown bin count)
author Chris Cannam
date Tue, 28 Jan 2014 18:52:22 +0000
parents 1d439494604c
children 6a94bb528e9d
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@0 7
Chris@52 8 This program is free software; you can redistribute it and/or
Chris@52 9 modify it under the terms of the GNU General Public License as
Chris@52 10 published by the Free Software Foundation; either version 2 of the
Chris@52 11 License, or (at your option) any later version. See the file
Chris@52 12 COPYING included with this distribution for more information.
Chris@0 13 */
Chris@0 14
Chris@0 15 /*
Chris@0 16 This is a modified version of a source file from the
Chris@0 17 Rosegarden MIDI and audio sequencer and notation editor.
Chris@17 18 This file copyright 2000-2006 Chris Cannam.
Chris@0 19 */
Chris@0 20
Chris@0 21 #ifndef _RINGBUFFER_H_
Chris@0 22 #define _RINGBUFFER_H_
Chris@0 23
Chris@0 24 #include <sys/types.h>
Chris@0 25
Chris@150 26 #include "system/System.h"
Chris@0 27
Chris@485 28 #include <cstring> // memcpy, memset &c
Chris@485 29
Chris@0 30 //#define DEBUG_RINGBUFFER 1
Chris@0 31
Chris@0 32 #ifdef DEBUG_RINGBUFFER
Chris@0 33 #include <iostream>
Chris@0 34 #endif
Chris@0 35
Chris@0 36 /**
Chris@0 37 * RingBuffer implements a lock-free ring buffer for one writer and N
Chris@0 38 * readers, that is to be used to store a sample type T.
Chris@0 39 *
Chris@0 40 * For efficiency, RingBuffer frequently initialises samples by
Chris@0 41 * writing zeroes into their memory space, so T should normally be a
Chris@0 42 * simple type that can safely be set to zero using memset.
Chris@0 43 */
Chris@0 44
Chris@0 45 template <typename T, int N = 1>
Chris@0 46 class RingBuffer
Chris@0 47 {
Chris@0 48 public:
Chris@0 49 /**
Chris@0 50 * Create a ring buffer with room to write n samples.
Chris@0 51 *
Chris@0 52 * Note that the internal storage size will actually be n+1
Chris@0 53 * samples, as one element is unavailable for administrative
Chris@0 54 * reasons. Since the ring buffer performs best if its size is a
Chris@0 55 * power of two, this means n should ideally be some power of two
Chris@0 56 * minus one.
Chris@0 57 */
Chris@0 58 RingBuffer(size_t n);
Chris@0 59
Chris@0 60 virtual ~RingBuffer();
Chris@0 61
Chris@0 62 /**
Chris@0 63 * Return the total capacity of the ring buffer in samples.
Chris@0 64 * (This is the argument n passed to the constructor.)
Chris@0 65 */
Chris@0 66 size_t getSize() const;
Chris@0 67
Chris@0 68 /**
Chris@835 69 * Return a new ring buffer (allocated with "new" -- caller must
Chris@835 70 * delete when no longer needed) of the given size, containing the
Chris@835 71 * same data as this one as perceived by reader 0 of this buffer.
Chris@835 72 * If another thread reads from or writes to this buffer during
Chris@835 73 * the call, the contents of the new buffer may be incomplete or
Chris@835 74 * inconsistent. If this buffer's data will not fit in the new
Chris@835 75 * size, the contents are undefined.
Chris@0 76 */
Chris@835 77 RingBuffer<T, N> *resized(size_t newSize) const;
Chris@0 78
Chris@0 79 /**
Chris@0 80 * Lock the ring buffer into physical memory. Returns true
Chris@0 81 * for success.
Chris@0 82 */
Chris@0 83 bool mlock();
Chris@0 84
Chris@0 85 /**
Chris@0 86 * Reset read and write pointers, thus emptying the buffer.
Chris@0 87 * Should be called from the write thread.
Chris@0 88 */
Chris@0 89 void reset();
Chris@0 90
Chris@0 91 /**
Chris@0 92 * Return the amount of data available for reading by reader R, in
Chris@0 93 * samples.
Chris@0 94 */
Chris@0 95 size_t getReadSpace(int R = 0) const;
Chris@0 96
Chris@0 97 /**
Chris@0 98 * Return the amount of space available for writing, in samples.
Chris@0 99 */
Chris@0 100 size_t getWriteSpace() const;
Chris@0 101
Chris@0 102 /**
Chris@0 103 * Read n samples from the buffer, for reader R. If fewer than n
Chris@0 104 * are available, the remainder will be zeroed out. Returns the
Chris@0 105 * number of samples actually read.
Chris@0 106 */
Chris@0 107 size_t read(T *destination, size_t n, int R = 0);
Chris@0 108
Chris@0 109 /**
Chris@0 110 * Read n samples from the buffer, for reader R, adding them to
Chris@0 111 * the destination. If fewer than n are available, the remainder
Chris@0 112 * will be left alone. Returns the number of samples actually
Chris@0 113 * read.
Chris@0 114 */
Chris@0 115 size_t readAdding(T *destination, size_t n, int R = 0);
Chris@0 116
Chris@0 117 /**
Chris@0 118 * Read one sample from the buffer, for reader R. If no sample is
Chris@0 119 * available, this will silently return zero. Calling this
Chris@0 120 * repeatedly is obviously slower than calling read once, but it
Chris@0 121 * may be good enough if you don't want to allocate a buffer to
Chris@0 122 * read into.
Chris@0 123 */
Chris@0 124 T readOne(int R = 0);
Chris@0 125
Chris@0 126 /**
Chris@0 127 * Read n samples from the buffer, if available, for reader R,
Chris@0 128 * without advancing the read pointer -- i.e. a subsequent read()
Chris@0 129 * or skip() will be necessary to empty the buffer. If fewer than
Chris@0 130 * n are available, the remainder will be zeroed out. Returns the
Chris@0 131 * number of samples actually read.
Chris@0 132 */
Chris@0 133 size_t peek(T *destination, size_t n, int R = 0) const;
Chris@0 134
Chris@0 135 /**
Chris@0 136 * Read one sample from the buffer, if available, without
Chris@0 137 * advancing the read pointer -- i.e. a subsequent read() or
Chris@0 138 * skip() will be necessary to empty the buffer. Returns zero if
Chris@0 139 * no sample was available.
Chris@0 140 */
Chris@0 141 T peekOne(int R = 0) const;
Chris@0 142
Chris@0 143 /**
Chris@0 144 * Pretend to read n samples from the buffer, for reader R,
Chris@0 145 * without actually returning them (i.e. discard the next n
Chris@0 146 * samples). Returns the number of samples actually available for
Chris@0 147 * discarding.
Chris@0 148 */
Chris@0 149 size_t skip(size_t n, int R = 0);
Chris@0 150
Chris@0 151 /**
Chris@0 152 * Write n samples to the buffer. If insufficient space is
Chris@0 153 * available, not all samples may actually be written. Returns
Chris@0 154 * the number of samples actually written.
Chris@0 155 */
Chris@0 156 size_t write(const T *source, size_t n);
Chris@0 157
Chris@0 158 /**
Chris@0 159 * Write n zero-value samples to the buffer. If insufficient
Chris@0 160 * space is available, not all zeros may actually be written.
Chris@0 161 * Returns the number of zeroes actually written.
Chris@0 162 */
Chris@0 163 size_t zero(size_t n);
Chris@0 164
Chris@0 165 protected:
Chris@574 166 T *m_buffer;
Chris@574 167 bool m_mlocked;
Chris@574 168 size_t m_writer;
Chris@574 169 size_t *m_readers;
Chris@574 170 size_t m_size;
Chris@575 171 size_t m_spare;
Chris@0 172
Chris@0 173 private:
Chris@0 174 RingBuffer(const RingBuffer &); // not provided
Chris@0 175 RingBuffer &operator=(const RingBuffer &); // not provided
Chris@0 176 };
Chris@0 177
Chris@0 178 template <typename T, int N>
Chris@0 179 RingBuffer<T, N>::RingBuffer(size_t n) :
Chris@0 180 m_buffer(new T[n + 1]),
Chris@574 181 m_mlocked(false),
Chris@0 182 m_writer(0),
Chris@574 183 m_readers(new size_t[N]),
Chris@574 184 m_size(n + 1)
Chris@0 185 {
Chris@0 186 #ifdef DEBUG_RINGBUFFER
Chris@0 187 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::RingBuffer(" << n << ")" << std::endl;
Chris@0 188 #endif
Chris@575 189 /*
Chris@575 190 std::cerr << "note: sizeof(RingBuffer<T,N> = " << sizeof(RingBuffer<T,N>) << ")" << std::endl;
Chris@0 191
Chris@575 192 std::cerr << "this = " << this << std::endl;
Chris@575 193 std::cerr << "&m_buffer = " << &m_buffer << std::endl;
Chris@575 194 std::cerr << "&m_mlocked = " << &m_mlocked << std::endl;
Chris@575 195 std::cerr << "&m_writer = " << &m_writer << std::endl;
Chris@575 196 std::cerr << "&m_readers = " << &m_readers << std::endl;
Chris@575 197 std::cerr << "&m_size = " << &m_size << std::endl;
Chris@575 198 */
Chris@576 199
Chris@0 200 for (int i = 0; i < N; ++i) m_readers[i] = 0;
Chris@0 201 }
Chris@0 202
Chris@0 203 template <typename T, int N>
Chris@0 204 RingBuffer<T, N>::~RingBuffer()
Chris@0 205 {
Chris@0 206 #ifdef DEBUG_RINGBUFFER
Chris@0 207 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::~RingBuffer" << std::endl;
Chris@0 208 #endif
Chris@0 209
Chris@574 210 delete[] m_readers;
Chris@574 211
Chris@0 212 if (m_mlocked) {
Chris@0 213 MUNLOCK((void *)m_buffer, m_size * sizeof(T));
Chris@0 214 }
Chris@0 215 delete[] m_buffer;
Chris@0 216 }
Chris@0 217
Chris@0 218 template <typename T, int N>
Chris@0 219 size_t
Chris@0 220 RingBuffer<T, N>::getSize() const
Chris@0 221 {
Chris@0 222 #ifdef DEBUG_RINGBUFFER
Chris@0 223 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getSize(): " << m_size-1 << std::endl;
Chris@0 224 #endif
Chris@0 225
Chris@0 226 return m_size - 1;
Chris@0 227 }
Chris@0 228
Chris@0 229 template <typename T, int N>
Chris@835 230 RingBuffer<T, N> *
Chris@835 231 RingBuffer<T, N>::resized(size_t newSize) const
Chris@0 232 {
Chris@0 233 #ifdef DEBUG_RINGBUFFER
Chris@835 234 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resized(" << newSize << ")" << std::endl;
Chris@0 235 #endif
Chris@0 236
Chris@835 237 RingBuffer<T, N> *newBuffer = new RingBuffer<T, N>(newSize);
Chris@0 238
Chris@835 239 int w = m_writer;
Chris@835 240 int r = m_readers[0];
Chris@835 241
Chris@835 242 while (r != w) {
Chris@835 243 T value = m_buffer[r];
Chris@835 244 newBuffer->write(&value, 1);
Chris@835 245 if (++r == m_size) r = 0;
Chris@0 246 }
Chris@0 247
Chris@835 248 return newBuffer;
Chris@0 249 }
Chris@0 250
Chris@0 251 template <typename T, int N>
Chris@0 252 bool
Chris@0 253 RingBuffer<T, N>::mlock()
Chris@0 254 {
Chris@0 255 if (MLOCK((void *)m_buffer, m_size * sizeof(T))) return false;
Chris@0 256 m_mlocked = true;
Chris@0 257 return true;
Chris@0 258 }
Chris@0 259
Chris@0 260 template <typename T, int N>
Chris@0 261 void
Chris@0 262 RingBuffer<T, N>::reset()
Chris@0 263 {
Chris@0 264 #ifdef DEBUG_RINGBUFFER
Chris@0 265 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::reset" << std::endl;
Chris@0 266 #endif
Chris@0 267
Chris@0 268 m_writer = 0;
Chris@0 269 for (int i = 0; i < N; ++i) m_readers[i] = 0;
Chris@0 270 }
Chris@0 271
Chris@0 272 template <typename T, int N>
Chris@0 273 size_t
Chris@0 274 RingBuffer<T, N>::getReadSpace(int R) const
Chris@0 275 {
Chris@0 276 size_t writer = m_writer;
Chris@0 277 size_t reader = m_readers[R];
Chris@0 278 size_t space = 0;
Chris@0 279
Chris@0 280 if (writer > reader) space = writer - reader;
Chris@0 281 else space = ((writer + m_size) - reader) % m_size;
Chris@0 282
Chris@0 283 #ifdef DEBUG_RINGBUFFER
Chris@0 284 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getReadSpace(" << R << "): " << space << std::endl;
Chris@0 285 #endif
Chris@0 286
Chris@0 287 return space;
Chris@0 288 }
Chris@0 289
Chris@0 290 template <typename T, int N>
Chris@0 291 size_t
Chris@0 292 RingBuffer<T, N>::getWriteSpace() const
Chris@0 293 {
Chris@0 294 size_t space = 0;
Chris@0 295 for (int i = 0; i < N; ++i) {
Chris@0 296 size_t here = (m_readers[i] + m_size - m_writer - 1) % m_size;
Chris@0 297 if (i == 0 || here < space) space = here;
Chris@0 298 }
Chris@0 299
Chris@0 300 #ifdef DEBUG_RINGBUFFER
Chris@0 301 size_t rs(getReadSpace()), rp(m_readers[0]);
Chris@0 302
Chris@0 303 std::cerr << "RingBuffer: write space " << space << ", read space "
Chris@0 304 << rs << ", total " << (space + rs) << ", m_size " << m_size << std::endl;
Chris@0 305 std::cerr << "RingBuffer: reader " << rp << ", writer " << m_writer << std::endl;
Chris@0 306 #endif
Chris@0 307
Chris@0 308 #ifdef DEBUG_RINGBUFFER
Chris@0 309 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getWriteSpace(): " << space << std::endl;
Chris@0 310 #endif
Chris@0 311
Chris@0 312 return space;
Chris@0 313 }
Chris@0 314
Chris@0 315 template <typename T, int N>
Chris@0 316 size_t
Chris@0 317 RingBuffer<T, N>::read(T *destination, size_t n, int R)
Chris@0 318 {
Chris@0 319 #ifdef DEBUG_RINGBUFFER
Chris@0 320 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read(dest, " << n << ", " << R << ")" << std::endl;
Chris@0 321 #endif
Chris@0 322
Chris@0 323 size_t available = getReadSpace(R);
Chris@0 324 if (n > available) {
Chris@0 325 #ifdef DEBUG_RINGBUFFER
Chris@0 326 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 327 << std::endl;
Chris@0 328 #endif
Chris@0 329 memset(destination + available, 0, (n - available) * sizeof(T));
Chris@0 330 n = available;
Chris@0 331 }
Chris@0 332 if (n == 0) return n;
Chris@0 333
Chris@0 334 size_t here = m_size - m_readers[R];
Chris@0 335 if (here >= n) {
Chris@0 336 memcpy(destination, m_buffer + m_readers[R], n * sizeof(T));
Chris@0 337 } else {
Chris@0 338 memcpy(destination, m_buffer + m_readers[R], here * sizeof(T));
Chris@0 339 memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
Chris@0 340 }
Chris@0 341
Chris@835 342 MBARRIER();
Chris@0 343 m_readers[R] = (m_readers[R] + n) % m_size;
Chris@0 344
Chris@0 345 #ifdef DEBUG_RINGBUFFER
Chris@0 346 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read: read " << n << ", reader now " << m_readers[R] << std::endl;
Chris@0 347 #endif
Chris@0 348
Chris@0 349 return n;
Chris@0 350 }
Chris@0 351
Chris@0 352 template <typename T, int N>
Chris@0 353 size_t
Chris@0 354 RingBuffer<T, N>::readAdding(T *destination, size_t n, int R)
Chris@0 355 {
Chris@0 356 #ifdef DEBUG_RINGBUFFER
Chris@0 357 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readAdding(dest, " << n << ", " << R << ")" << std::endl;
Chris@0 358 #endif
Chris@0 359
Chris@0 360 size_t available = getReadSpace(R);
Chris@0 361 if (n > available) {
Chris@0 362 #ifdef DEBUG_RINGBUFFER
Chris@0 363 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 364 << std::endl;
Chris@0 365 #endif
Chris@0 366 n = available;
Chris@0 367 }
Chris@0 368 if (n == 0) return n;
Chris@0 369
Chris@0 370 size_t here = m_size - m_readers[R];
Chris@0 371
Chris@0 372 if (here >= n) {
Chris@0 373 for (size_t i = 0; i < n; ++i) {
Chris@0 374 destination[i] += (m_buffer + m_readers[R])[i];
Chris@0 375 }
Chris@0 376 } else {
Chris@0 377 for (size_t i = 0; i < here; ++i) {
Chris@0 378 destination[i] += (m_buffer + m_readers[R])[i];
Chris@0 379 }
Chris@0 380 for (size_t i = 0; i < (n - here); ++i) {
Chris@0 381 destination[i + here] += m_buffer[i];
Chris@0 382 }
Chris@0 383 }
Chris@0 384
Chris@835 385 MBARRIER();
Chris@0 386 m_readers[R] = (m_readers[R] + n) % m_size;
Chris@0 387 return n;
Chris@0 388 }
Chris@0 389
Chris@0 390 template <typename T, int N>
Chris@0 391 T
Chris@0 392 RingBuffer<T, N>::readOne(int R)
Chris@0 393 {
Chris@0 394 #ifdef DEBUG_RINGBUFFER
Chris@0 395 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readOne(" << R << ")" << std::endl;
Chris@0 396 #endif
Chris@0 397
Chris@0 398 if (m_writer == m_readers[R]) {
Chris@0 399 #ifdef DEBUG_RINGBUFFER
Chris@0 400 std::cerr << "WARNING: No sample available"
Chris@0 401 << std::endl;
Chris@0 402 #endif
Chris@0 403 T t;
Chris@0 404 memset(&t, 0, sizeof(T));
Chris@0 405 return t;
Chris@0 406 }
Chris@0 407 T value = m_buffer[m_readers[R]];
Chris@835 408 MBARRIER();
Chris@0 409 if (++m_readers[R] == m_size) m_readers[R] = 0;
Chris@0 410 return value;
Chris@0 411 }
Chris@0 412
Chris@0 413 template <typename T, int N>
Chris@0 414 size_t
Chris@0 415 RingBuffer<T, N>::peek(T *destination, size_t n, int R) const
Chris@0 416 {
Chris@0 417 #ifdef DEBUG_RINGBUFFER
Chris@0 418 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(dest, " << n << ", " << R << ")" << std::endl;
Chris@0 419 #endif
Chris@0 420
Chris@0 421 size_t available = getReadSpace(R);
Chris@0 422 if (n > available) {
Chris@0 423 #ifdef DEBUG_RINGBUFFER
Chris@0 424 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 425 << std::endl;
Chris@0 426 #endif
Chris@0 427 memset(destination + available, 0, (n - available) * sizeof(T));
Chris@0 428 n = available;
Chris@0 429 }
Chris@0 430 if (n == 0) return n;
Chris@0 431
Chris@0 432 size_t here = m_size - m_readers[R];
Chris@0 433 if (here >= n) {
Chris@0 434 memcpy(destination, m_buffer + m_readers[R], n * sizeof(T));
Chris@0 435 } else {
Chris@0 436 memcpy(destination, m_buffer + m_readers[R], here * sizeof(T));
Chris@0 437 memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
Chris@0 438 }
Chris@0 439
Chris@0 440 #ifdef DEBUG_RINGBUFFER
Chris@0 441 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek: read " << n << std::endl;
Chris@0 442 #endif
Chris@0 443
Chris@0 444 return n;
Chris@0 445 }
Chris@0 446
Chris@0 447 template <typename T, int N>
Chris@0 448 T
Chris@0 449 RingBuffer<T, N>::peekOne(int R) const
Chris@0 450 {
Chris@0 451 #ifdef DEBUG_RINGBUFFER
Chris@0 452 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(" << R << ")" << std::endl;
Chris@0 453 #endif
Chris@0 454
Chris@0 455 if (m_writer == m_readers[R]) {
Chris@0 456 #ifdef DEBUG_RINGBUFFER
Chris@0 457 std::cerr << "WARNING: No sample available"
Chris@0 458 << std::endl;
Chris@0 459 #endif
Chris@0 460 T t;
Chris@0 461 memset(&t, 0, sizeof(T));
Chris@0 462 return t;
Chris@0 463 }
Chris@0 464 T value = m_buffer[m_readers[R]];
Chris@0 465 return value;
Chris@0 466 }
Chris@0 467
Chris@0 468 template <typename T, int N>
Chris@0 469 size_t
Chris@0 470 RingBuffer<T, N>::skip(size_t n, int R)
Chris@0 471 {
Chris@0 472 #ifdef DEBUG_RINGBUFFER
Chris@0 473 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::skip(" << n << ", " << R << ")" << std::endl;
Chris@0 474 #endif
Chris@0 475
Chris@0 476 size_t available = getReadSpace(R);
Chris@0 477 if (n > available) {
Chris@0 478 #ifdef DEBUG_RINGBUFFER
Chris@0 479 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 480 << std::endl;
Chris@0 481 #endif
Chris@0 482 n = available;
Chris@0 483 }
Chris@0 484 if (n == 0) return n;
Chris@0 485 m_readers[R] = (m_readers[R] + n) % m_size;
Chris@0 486 return n;
Chris@0 487 }
Chris@0 488
Chris@0 489 template <typename T, int N>
Chris@0 490 size_t
Chris@0 491 RingBuffer<T, N>::write(const T *source, size_t n)
Chris@0 492 {
Chris@0 493 #ifdef DEBUG_RINGBUFFER
Chris@0 494 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write(" << n << ")" << std::endl;
Chris@0 495 #endif
Chris@0 496
Chris@0 497 size_t available = getWriteSpace();
Chris@0 498 if (n > available) {
Chris@0 499 #ifdef DEBUG_RINGBUFFER
Chris@0 500 std::cerr << "WARNING: Only room for " << available << " samples"
Chris@0 501 << std::endl;
Chris@0 502 #endif
Chris@0 503 n = available;
Chris@0 504 }
Chris@0 505 if (n == 0) return n;
Chris@0 506
Chris@0 507 size_t here = m_size - m_writer;
Chris@0 508 if (here >= n) {
Chris@0 509 memcpy(m_buffer + m_writer, source, n * sizeof(T));
Chris@0 510 } else {
Chris@0 511 memcpy(m_buffer + m_writer, source, here * sizeof(T));
Chris@0 512 memcpy(m_buffer, source + here, (n - here) * sizeof(T));
Chris@0 513 }
Chris@0 514
Chris@835 515 MBARRIER();
Chris@0 516 m_writer = (m_writer + n) % m_size;
Chris@0 517
Chris@0 518 #ifdef DEBUG_RINGBUFFER
Chris@0 519 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write: wrote " << n << ", writer now " << m_writer << std::endl;
Chris@0 520 #endif
Chris@0 521
Chris@0 522 return n;
Chris@0 523 }
Chris@0 524
Chris@0 525 template <typename T, int N>
Chris@0 526 size_t
Chris@0 527 RingBuffer<T, N>::zero(size_t n)
Chris@0 528 {
Chris@0 529 #ifdef DEBUG_RINGBUFFER
Chris@0 530 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::zero(" << n << ")" << std::endl;
Chris@0 531 #endif
Chris@0 532
Chris@0 533 size_t available = getWriteSpace();
Chris@0 534 if (n > available) {
Chris@0 535 #ifdef DEBUG_RINGBUFFER
Chris@0 536 std::cerr << "WARNING: Only room for " << available << " samples"
Chris@0 537 << std::endl;
Chris@0 538 #endif
Chris@0 539 n = available;
Chris@0 540 }
Chris@0 541 if (n == 0) return n;
Chris@0 542
Chris@0 543 size_t here = m_size - m_writer;
Chris@0 544 if (here >= n) {
Chris@0 545 memset(m_buffer + m_writer, 0, n * sizeof(T));
Chris@0 546 } else {
Chris@0 547 memset(m_buffer + m_writer, 0, here * sizeof(T));
Chris@0 548 memset(m_buffer, 0, (n - here) * sizeof(T));
Chris@0 549 }
Chris@835 550
Chris@835 551 MBARRIER();
Chris@0 552 m_writer = (m_writer + n) % m_size;
Chris@0 553 return n;
Chris@0 554 }
Chris@0 555
Chris@0 556 #endif // _RINGBUFFER_H_