annotate base/RingBuffer.h @ 1622:172bd3374adf single-point

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