annotate base/RingBuffer.h @ 808:67003fb58ba4

Merge from branch "qt5". This revision actually builds with Qt4 (late releases) or Qt5, though it will warn on configure with Qt4.
author Chris Cannam
date Tue, 14 May 2013 12:36:05 +0100
parents 2ba202c5be8d
children 1d439494604c
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@574 163 T *m_buffer;
Chris@574 164 bool m_mlocked;
Chris@574 165 size_t m_writer;
Chris@574 166 size_t *m_readers;
Chris@574 167 size_t m_size;
Chris@575 168 size_t m_spare;
Chris@0 169
Chris@0 170 static Scavenger<ScavengerArrayWrapper<T> > m_scavenger;
Chris@0 171
Chris@0 172 private:
Chris@0 173 RingBuffer(const RingBuffer &); // not provided
Chris@0 174 RingBuffer &operator=(const RingBuffer &); // not provided
Chris@0 175 };
Chris@0 176
Chris@0 177 template <typename T, int N>
Chris@0 178 Scavenger<ScavengerArrayWrapper<T> > RingBuffer<T, N>::m_scavenger;
Chris@0 179
Chris@0 180 template <typename T, int N>
Chris@0 181 RingBuffer<T, N>::RingBuffer(size_t n) :
Chris@0 182 m_buffer(new T[n + 1]),
Chris@574 183 m_mlocked(false),
Chris@0 184 m_writer(0),
Chris@574 185 m_readers(new size_t[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 m_scavenger.scavenge();
Chris@0 205 }
Chris@0 206
Chris@0 207 template <typename T, int N>
Chris@0 208 RingBuffer<T, N>::~RingBuffer()
Chris@0 209 {
Chris@0 210 #ifdef DEBUG_RINGBUFFER
Chris@0 211 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::~RingBuffer" << std::endl;
Chris@0 212 #endif
Chris@0 213
Chris@574 214 delete[] m_readers;
Chris@574 215
Chris@0 216 if (m_mlocked) {
Chris@0 217 MUNLOCK((void *)m_buffer, m_size * sizeof(T));
Chris@0 218 }
Chris@0 219 delete[] m_buffer;
Chris@0 220
Chris@0 221 m_scavenger.scavenge();
Chris@0 222 }
Chris@0 223
Chris@0 224 template <typename T, int N>
Chris@0 225 size_t
Chris@0 226 RingBuffer<T, N>::getSize() const
Chris@0 227 {
Chris@0 228 #ifdef DEBUG_RINGBUFFER
Chris@0 229 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getSize(): " << m_size-1 << std::endl;
Chris@0 230 #endif
Chris@0 231
Chris@0 232 return m_size - 1;
Chris@0 233 }
Chris@0 234
Chris@0 235 template <typename T, int N>
Chris@0 236 void
Chris@0 237 RingBuffer<T, N>::resize(size_t newSize)
Chris@0 238 {
Chris@0 239 #ifdef DEBUG_RINGBUFFER
Chris@0 240 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resize(" << newSize << ")" << std::endl;
Chris@0 241 #endif
Chris@0 242
Chris@0 243 m_scavenger.scavenge();
Chris@0 244
Chris@0 245 if (m_mlocked) {
Chris@0 246 MUNLOCK((void *)m_buffer, m_size * sizeof(T));
Chris@0 247 }
Chris@0 248
Chris@0 249 m_scavenger.claim(new ScavengerArrayWrapper<T>(m_buffer));
Chris@0 250
Chris@0 251 reset();
Chris@0 252 m_buffer = new T[newSize + 1];
Chris@0 253 m_size = newSize + 1;
Chris@0 254
Chris@0 255 if (m_mlocked) {
Chris@0 256 if (MLOCK((void *)m_buffer, m_size * sizeof(T))) {
Chris@0 257 m_mlocked = false;
Chris@0 258 }
Chris@0 259 }
Chris@0 260 }
Chris@0 261
Chris@0 262 template <typename T, int N>
Chris@0 263 bool
Chris@0 264 RingBuffer<T, N>::mlock()
Chris@0 265 {
Chris@0 266 if (MLOCK((void *)m_buffer, m_size * sizeof(T))) return false;
Chris@0 267 m_mlocked = true;
Chris@0 268 return true;
Chris@0 269 }
Chris@0 270
Chris@0 271 template <typename T, int N>
Chris@0 272 void
Chris@0 273 RingBuffer<T, N>::reset()
Chris@0 274 {
Chris@0 275 #ifdef DEBUG_RINGBUFFER
Chris@0 276 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::reset" << std::endl;
Chris@0 277 #endif
Chris@0 278
Chris@0 279 m_writer = 0;
Chris@0 280 for (int i = 0; i < N; ++i) m_readers[i] = 0;
Chris@0 281 }
Chris@0 282
Chris@0 283 template <typename T, int N>
Chris@0 284 size_t
Chris@0 285 RingBuffer<T, N>::getReadSpace(int R) const
Chris@0 286 {
Chris@0 287 size_t writer = m_writer;
Chris@0 288 size_t reader = m_readers[R];
Chris@0 289 size_t space = 0;
Chris@0 290
Chris@0 291 if (writer > reader) space = writer - reader;
Chris@0 292 else space = ((writer + m_size) - reader) % m_size;
Chris@0 293
Chris@0 294 #ifdef DEBUG_RINGBUFFER
Chris@0 295 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getReadSpace(" << R << "): " << space << std::endl;
Chris@0 296 #endif
Chris@0 297
Chris@0 298 return space;
Chris@0 299 }
Chris@0 300
Chris@0 301 template <typename T, int N>
Chris@0 302 size_t
Chris@0 303 RingBuffer<T, N>::getWriteSpace() const
Chris@0 304 {
Chris@0 305 size_t space = 0;
Chris@0 306 for (int i = 0; i < N; ++i) {
Chris@0 307 size_t here = (m_readers[i] + m_size - m_writer - 1) % m_size;
Chris@0 308 if (i == 0 || here < space) space = here;
Chris@0 309 }
Chris@0 310
Chris@0 311 #ifdef DEBUG_RINGBUFFER
Chris@0 312 size_t rs(getReadSpace()), rp(m_readers[0]);
Chris@0 313
Chris@0 314 std::cerr << "RingBuffer: write space " << space << ", read space "
Chris@0 315 << rs << ", total " << (space + rs) << ", m_size " << m_size << std::endl;
Chris@0 316 std::cerr << "RingBuffer: reader " << rp << ", writer " << m_writer << std::endl;
Chris@0 317 #endif
Chris@0 318
Chris@0 319 #ifdef DEBUG_RINGBUFFER
Chris@0 320 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getWriteSpace(): " << space << std::endl;
Chris@0 321 #endif
Chris@0 322
Chris@0 323 return space;
Chris@0 324 }
Chris@0 325
Chris@0 326 template <typename T, int N>
Chris@0 327 size_t
Chris@0 328 RingBuffer<T, N>::read(T *destination, size_t n, int R)
Chris@0 329 {
Chris@0 330 #ifdef DEBUG_RINGBUFFER
Chris@0 331 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read(dest, " << n << ", " << R << ")" << std::endl;
Chris@0 332 #endif
Chris@0 333
Chris@0 334 size_t available = getReadSpace(R);
Chris@0 335 if (n > available) {
Chris@0 336 #ifdef DEBUG_RINGBUFFER
Chris@0 337 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 338 << std::endl;
Chris@0 339 #endif
Chris@0 340 memset(destination + available, 0, (n - available) * sizeof(T));
Chris@0 341 n = available;
Chris@0 342 }
Chris@0 343 if (n == 0) return n;
Chris@0 344
Chris@0 345 size_t here = m_size - m_readers[R];
Chris@0 346 if (here >= n) {
Chris@0 347 memcpy(destination, m_buffer + m_readers[R], n * sizeof(T));
Chris@0 348 } else {
Chris@0 349 memcpy(destination, m_buffer + m_readers[R], here * sizeof(T));
Chris@0 350 memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
Chris@0 351 }
Chris@0 352
Chris@0 353 m_readers[R] = (m_readers[R] + n) % m_size;
Chris@0 354
Chris@0 355 #ifdef DEBUG_RINGBUFFER
Chris@0 356 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read: read " << n << ", reader now " << m_readers[R] << std::endl;
Chris@0 357 #endif
Chris@0 358
Chris@0 359 return n;
Chris@0 360 }
Chris@0 361
Chris@0 362 template <typename T, int N>
Chris@0 363 size_t
Chris@0 364 RingBuffer<T, N>::readAdding(T *destination, size_t n, int R)
Chris@0 365 {
Chris@0 366 #ifdef DEBUG_RINGBUFFER
Chris@0 367 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readAdding(dest, " << n << ", " << R << ")" << std::endl;
Chris@0 368 #endif
Chris@0 369
Chris@0 370 size_t available = getReadSpace(R);
Chris@0 371 if (n > available) {
Chris@0 372 #ifdef DEBUG_RINGBUFFER
Chris@0 373 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 374 << std::endl;
Chris@0 375 #endif
Chris@0 376 n = available;
Chris@0 377 }
Chris@0 378 if (n == 0) return n;
Chris@0 379
Chris@0 380 size_t here = m_size - m_readers[R];
Chris@0 381
Chris@0 382 if (here >= n) {
Chris@0 383 for (size_t i = 0; i < n; ++i) {
Chris@0 384 destination[i] += (m_buffer + m_readers[R])[i];
Chris@0 385 }
Chris@0 386 } else {
Chris@0 387 for (size_t i = 0; i < here; ++i) {
Chris@0 388 destination[i] += (m_buffer + m_readers[R])[i];
Chris@0 389 }
Chris@0 390 for (size_t i = 0; i < (n - here); ++i) {
Chris@0 391 destination[i + here] += m_buffer[i];
Chris@0 392 }
Chris@0 393 }
Chris@0 394
Chris@0 395 m_readers[R] = (m_readers[R] + n) % m_size;
Chris@0 396 return n;
Chris@0 397 }
Chris@0 398
Chris@0 399 template <typename T, int N>
Chris@0 400 T
Chris@0 401 RingBuffer<T, N>::readOne(int R)
Chris@0 402 {
Chris@0 403 #ifdef DEBUG_RINGBUFFER
Chris@0 404 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readOne(" << R << ")" << std::endl;
Chris@0 405 #endif
Chris@0 406
Chris@0 407 if (m_writer == m_readers[R]) {
Chris@0 408 #ifdef DEBUG_RINGBUFFER
Chris@0 409 std::cerr << "WARNING: No sample available"
Chris@0 410 << std::endl;
Chris@0 411 #endif
Chris@0 412 T t;
Chris@0 413 memset(&t, 0, sizeof(T));
Chris@0 414 return t;
Chris@0 415 }
Chris@0 416 T value = m_buffer[m_readers[R]];
Chris@0 417 if (++m_readers[R] == m_size) m_readers[R] = 0;
Chris@0 418 return value;
Chris@0 419 }
Chris@0 420
Chris@0 421 template <typename T, int N>
Chris@0 422 size_t
Chris@0 423 RingBuffer<T, N>::peek(T *destination, size_t n, int R) const
Chris@0 424 {
Chris@0 425 #ifdef DEBUG_RINGBUFFER
Chris@0 426 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(dest, " << n << ", " << R << ")" << std::endl;
Chris@0 427 #endif
Chris@0 428
Chris@0 429 size_t available = getReadSpace(R);
Chris@0 430 if (n > available) {
Chris@0 431 #ifdef DEBUG_RINGBUFFER
Chris@0 432 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 433 << std::endl;
Chris@0 434 #endif
Chris@0 435 memset(destination + available, 0, (n - available) * sizeof(T));
Chris@0 436 n = available;
Chris@0 437 }
Chris@0 438 if (n == 0) return n;
Chris@0 439
Chris@0 440 size_t here = m_size - m_readers[R];
Chris@0 441 if (here >= n) {
Chris@0 442 memcpy(destination, m_buffer + m_readers[R], n * sizeof(T));
Chris@0 443 } else {
Chris@0 444 memcpy(destination, m_buffer + m_readers[R], here * sizeof(T));
Chris@0 445 memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
Chris@0 446 }
Chris@0 447
Chris@0 448 #ifdef DEBUG_RINGBUFFER
Chris@0 449 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek: read " << n << std::endl;
Chris@0 450 #endif
Chris@0 451
Chris@0 452 return n;
Chris@0 453 }
Chris@0 454
Chris@0 455 template <typename T, int N>
Chris@0 456 T
Chris@0 457 RingBuffer<T, N>::peekOne(int R) const
Chris@0 458 {
Chris@0 459 #ifdef DEBUG_RINGBUFFER
Chris@0 460 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(" << R << ")" << std::endl;
Chris@0 461 #endif
Chris@0 462
Chris@0 463 if (m_writer == m_readers[R]) {
Chris@0 464 #ifdef DEBUG_RINGBUFFER
Chris@0 465 std::cerr << "WARNING: No sample available"
Chris@0 466 << std::endl;
Chris@0 467 #endif
Chris@0 468 T t;
Chris@0 469 memset(&t, 0, sizeof(T));
Chris@0 470 return t;
Chris@0 471 }
Chris@0 472 T value = m_buffer[m_readers[R]];
Chris@0 473 return value;
Chris@0 474 }
Chris@0 475
Chris@0 476 template <typename T, int N>
Chris@0 477 size_t
Chris@0 478 RingBuffer<T, N>::skip(size_t n, int R)
Chris@0 479 {
Chris@0 480 #ifdef DEBUG_RINGBUFFER
Chris@0 481 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::skip(" << n << ", " << R << ")" << std::endl;
Chris@0 482 #endif
Chris@0 483
Chris@0 484 size_t available = getReadSpace(R);
Chris@0 485 if (n > available) {
Chris@0 486 #ifdef DEBUG_RINGBUFFER
Chris@0 487 std::cerr << "WARNING: Only " << available << " samples available"
Chris@0 488 << std::endl;
Chris@0 489 #endif
Chris@0 490 n = available;
Chris@0 491 }
Chris@0 492 if (n == 0) return n;
Chris@0 493 m_readers[R] = (m_readers[R] + n) % m_size;
Chris@0 494 return n;
Chris@0 495 }
Chris@0 496
Chris@0 497 template <typename T, int N>
Chris@0 498 size_t
Chris@0 499 RingBuffer<T, N>::write(const T *source, size_t n)
Chris@0 500 {
Chris@0 501 #ifdef DEBUG_RINGBUFFER
Chris@0 502 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write(" << n << ")" << std::endl;
Chris@0 503 #endif
Chris@0 504
Chris@0 505 size_t available = getWriteSpace();
Chris@0 506 if (n > available) {
Chris@0 507 #ifdef DEBUG_RINGBUFFER
Chris@0 508 std::cerr << "WARNING: Only room for " << available << " samples"
Chris@0 509 << std::endl;
Chris@0 510 #endif
Chris@0 511 n = available;
Chris@0 512 }
Chris@0 513 if (n == 0) return n;
Chris@0 514
Chris@0 515 size_t here = m_size - m_writer;
Chris@0 516 if (here >= n) {
Chris@0 517 memcpy(m_buffer + m_writer, source, n * sizeof(T));
Chris@0 518 } else {
Chris@0 519 memcpy(m_buffer + m_writer, source, here * sizeof(T));
Chris@0 520 memcpy(m_buffer, source + here, (n - here) * sizeof(T));
Chris@0 521 }
Chris@0 522
Chris@0 523 m_writer = (m_writer + n) % m_size;
Chris@0 524
Chris@0 525 #ifdef DEBUG_RINGBUFFER
Chris@0 526 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write: wrote " << n << ", writer now " << m_writer << std::endl;
Chris@0 527 #endif
Chris@0 528
Chris@0 529 return n;
Chris@0 530 }
Chris@0 531
Chris@0 532 template <typename T, int N>
Chris@0 533 size_t
Chris@0 534 RingBuffer<T, N>::zero(size_t n)
Chris@0 535 {
Chris@0 536 #ifdef DEBUG_RINGBUFFER
Chris@0 537 std::cerr << "RingBuffer<T," << N << ">[" << this << "]::zero(" << n << ")" << std::endl;
Chris@0 538 #endif
Chris@0 539
Chris@0 540 size_t available = getWriteSpace();
Chris@0 541 if (n > available) {
Chris@0 542 #ifdef DEBUG_RINGBUFFER
Chris@0 543 std::cerr << "WARNING: Only room for " << available << " samples"
Chris@0 544 << std::endl;
Chris@0 545 #endif
Chris@0 546 n = available;
Chris@0 547 }
Chris@0 548 if (n == 0) return n;
Chris@0 549
Chris@0 550 size_t here = m_size - m_writer;
Chris@0 551 if (here >= n) {
Chris@0 552 memset(m_buffer + m_writer, 0, n * sizeof(T));
Chris@0 553 } else {
Chris@0 554 memset(m_buffer + m_writer, 0, here * sizeof(T));
Chris@0 555 memset(m_buffer, 0, (n - here) * sizeof(T));
Chris@0 556 }
Chris@0 557
Chris@0 558 m_writer = (m_writer + n) % m_size;
Chris@0 559 return n;
Chris@0 560 }
Chris@0 561
Chris@0 562 #endif // _RINGBUFFER_H_