annotate base/RingBuffer.h @ 282:d9319859a4cf tip

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