summaryrefslogtreecommitdiffstats
path: root/raul/RingBuffer.hpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-05-23 03:41:45 +0000
committerDavid Robillard <d@drobilla.net>2008-05-23 03:41:45 +0000
commit6ebefb4c8b523ecac35b7440907ef9e57d0154f0 (patch)
treecb2f25b531b9b38a642767a7fd21c5f285ca4623 /raul/RingBuffer.hpp
parent264ce503aebaa87d275f23d1ea1a33034083b190 (diff)
downloadraul-6ebefb4c8b523ecac35b7440907ef9e57d0154f0.tar.gz
raul-6ebefb4c8b523ecac35b7440907ef9e57d0154f0.tar.bz2
raul-6ebefb4c8b523ecac35b7440907ef9e57d0154f0.zip
Merge improvemennts to MIDI stuff from Ardour.
git-svn-id: http://svn.drobilla.net/lad/raul@1227 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'raul/RingBuffer.hpp')
-rw-r--r--raul/RingBuffer.hpp114
1 files changed, 89 insertions, 25 deletions
diff --git a/raul/RingBuffer.hpp b/raul/RingBuffer.hpp
index 4098a2f..dff1464 100644
--- a/raul/RingBuffer.hpp
+++ b/raul/RingBuffer.hpp
@@ -1,5 +1,5 @@
/* This file is part of Raul.
- * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ * Copyright (C) 2007-2008 Dave Robillard <http://drobilla.net>
*
* Raul is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
@@ -19,6 +19,7 @@
#define RAUL_RING_BUFFER_HPP
#include <cassert>
+#include <iostream>
#include <glib.h>
namespace Raul {
@@ -62,7 +63,7 @@ public:
if (w > r) {
return ((r - w + _size) % _size) - 1;
- } else if(w < r) {
+ } else if (w < r) {
return (r - w) - 1;
} else {
return _size - 1;
@@ -83,20 +84,65 @@ public:
size_t capacity() const { return _size; }
+ size_t peek(size_t size, T* dst);
+ bool full_peek(size_t size, T* dst);
+
size_t read(size_t size, T* dst);
- void write(size_t size, const T* src);
-
bool full_read(size_t size, T* dst);
+ bool skip(size_t size);
+
+ void write(size_t size, const T* src);
+
protected:
- mutable gint _write_ptr;
- mutable gint _read_ptr;
+ mutable int _write_ptr;
+ mutable int _read_ptr;
size_t _size; ///< Size (capacity) in bytes
- T* _buf; ///< size, event, size, event...
+ T* _buf; ///< size, event, size, event...
};
+/** Peek at the ringbuffer (read w/o advancing read pointer).
+ *
+ * Note that a full read may not be done if the data wraps around.
+ * Caller must check return value and call again if necessary, or use the
+ * full_peek method which does this automatically.
+ */
+template<typename T>
+size_t
+RingBuffer<T>::peek(size_t size, T* dst)
+{
+ const size_t priv_read_ptr = g_atomic_int_get(&_read_ptr);
+
+ const size_t read_size = (priv_read_ptr + size < _size)
+ ? size
+ : _size - priv_read_ptr;
+
+ memcpy(dst, &_buf[priv_read_ptr], read_size);
+
+ return read_size;
+}
+
+
+template<typename T>
+bool
+RingBuffer<T>::full_peek(size_t size, T* dst)
+{
+ if (read_space() < size) {
+ return false;
+ }
+
+ const size_t read_size = peek(size, dst);
+
+ if (read_size < size) {
+ peek(size - read_size, dst + read_size);
+ }
+
+ return true;
+}
+
+
/** Read from the ringbuffer.
*
* Note that a full read may not be done if the data wraps around.
@@ -122,6 +168,40 @@ RingBuffer<T>::read(size_t size, T* dst)
template<typename T>
+bool
+RingBuffer<T>::full_read(size_t size, T* dst)
+{
+ if (read_space() < size) {
+ return false;
+ }
+
+ const size_t read_size = read(size, dst);
+
+ if (read_size < size) {
+ read(size - read_size, dst + read_size);
+ }
+
+ return true;
+}
+
+
+template<typename T>
+bool
+RingBuffer<T>::skip(size_t size)
+{
+ if (read_space() < size) {
+ std::cerr << "WARNING: Attempt to skip past end of MIDI ring buffer" << std::endl;
+ return false;
+ }
+
+ const size_t priv_read_ptr = g_atomic_int_get(&_read_ptr);
+ g_atomic_int_set(&_read_ptr, (priv_read_ptr + size) % _size);
+
+ return true;
+}
+
+
+template<typename T>
inline void
RingBuffer<T>::write(size_t size, const T* src)
{
@@ -129,33 +209,17 @@ RingBuffer<T>::write(size_t size, const T* src)
if (priv_write_ptr + size <= _size) {
memcpy(&_buf[priv_write_ptr], src, size);
- g_atomic_int_set(&_write_ptr, (priv_write_ptr + size) % _size);
+ g_atomic_int_set(&_write_ptr, (priv_write_ptr + size) % _size);
} else {
const size_t this_size = _size - priv_write_ptr;
assert(this_size < size);
assert(priv_write_ptr + this_size <= _size);
memcpy(&_buf[priv_write_ptr], src, this_size);
memcpy(&_buf[0], src+this_size, size - this_size);
- g_atomic_int_set(&_write_ptr, size - this_size);
+ g_atomic_int_set(&_write_ptr, size - this_size);
}
}
-
-template<typename T>
-bool
-RingBuffer<T>::full_read(size_t size, T* dst)
-{
- if (read_space() < size)
- return false;
-
- const size_t read_size = read(size, dst);
-
- if (read_size < size)
- read(size - read_size, dst + read_size);
-
- return true;
-}
-
} // namespace Raul