annotate base/RingBuffer.h @ 1008:d9e0e59a1581

When using an aggregate model to pass data to a transform, zero-pad the shorter input to the duration of the longer rather than truncating the longer. (This is better behaviour for e.g. MATCH, and in any case the code was previously truncating incorrectly and ending up with garbage data at the end.)
author Chris Cannam
date Fri, 14 Nov 2014 13:51:33 +0000
parents 6a94bb528e9d
children 48e9f538e6e9
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@928 58 RingBuffer(int 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@928 66 int 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@928 77 RingBuffer<T, N> *resized(int 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@928 95 int 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@928 100 int 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@928 107 int read(T *destination, int 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@928 115 int readAdding(T *destination, int 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@928 133 int peek(T *destination, int 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@928 149 int skip(int 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@928 156 int write(const T *source, int 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@928 163 int zero(int n);
Chris@0 164
Chris@0 165 protected:
Chris@928 166 T *m_buffer;
Chris@928 167 bool m_mlocked;
Chris@928 168 int m_writer;
Chris@928 169 int *m_readers;
Chris@928 170 int m_size;
Chris@928 171 int 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@928 179 RingBuffer<T, N>::RingBuffer(int n) :
Chris@0 180 m_buffer(new T[n + 1]),
Chris@574 181 m_mlocked(false),
Chris@0 182 m_writer(0),
Chris@928 183 m_readers(new int[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@928 219 int
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@928 231 RingBuffer<T, N>::resized(int 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@928 273 int
Chris@0 274 RingBuffer<T, N>::getReadSpace(int R) const
Chris@0 275 {
Chris@928 276 int writer = m_writer;
Chris@928 277 int reader = m_readers[R];
Chris@928 278 int 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@928 291 int
Chris@0 292 RingBuffer<T, N>::getWriteSpace() const
Chris@0 293 {
Chris@928 294 int space = 0;
Chris@0 295 for (int i = 0; i < N; ++i) {
Chris@928 296 int 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@928 301 int 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@928 316 int
Chris@928 317 RingBuffer<T, N>::read(T *destination, int 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@928 323 int 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@928 334 int 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@928 353 int
Chris@928 354 RingBuffer<T, N>::readAdding(T *destination, int 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@928 360 int 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@928 370 int here = m_size - m_readers[R];
Chris@0 371
Chris@0 372 if (here >= n) {
Chris@928 373 for (int i = 0; i < n; ++i) {
Chris@0 374 destination[i] += (m_buffer + m_readers[R])[i];
Chris@0 375 }
Chris@0 376 } else {
Chris@928 377 for (int i = 0; i < here; ++i) {
Chris@0 378 destination[i] += (m_buffer + m_readers[R])[i];
Chris@0 379 }
Chris@928 380 for (int 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@928 414 int
Chris@928 415 RingBuffer<T, N>::peek(T *destination, int 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@928 421 int 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@928 432 int 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@928 469 int
Chris@928 470 RingBuffer<T, N>::skip(int 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@928 476 int 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@928 490 int
Chris@928 491 RingBuffer<T, N>::write(const T *source, int 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@928 497 int 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@928 507 int 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@928 526 int
Chris@928 527 RingBuffer<T, N>::zero(int 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@928 533 int 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@928 543 int 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_