annotate base/RingBuffer.h @ 316:3a6725f285d6

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