annotate base/RingBuffer.h @ 490:c3fb8258e34d

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