buffer.hh
#ifndef __SDR_BUFFER_HH__
#define __SDR_BUFFER_HH__
#include <vector>
#include <map>
#include <list>
#include <ostream>
#include <complex>
#include <inttypes.h>
#include <cstdlib>
#include <cstring>
#include "config.hh"
#include "exception.hh"
namespace sdr {
// Forward declarations
class RawBuffer;
class BufferOwner {
public:
virtual void bufferUnused(const RawBuffer &buffer) = 0;
};
class RawBuffer
{
public:
RawBuffer();
RawBuffer(char *data, size_t offset, size_t len);
RawBuffer(size_t N, BufferOwner *owner=0);
RawBuffer(const RawBuffer &other);
RawBuffer(const RawBuffer &other, size_t offset, size_t len);
virtual ~RawBuffer();
inline const RawBuffer &operator= (const RawBuffer &other) {
// Now, reference new one
_ptr = other._ptr;
_storage_size = other._storage_size;
_b_offset = other._b_offset;
_b_length = other._b_length;
_refcount = other._refcount;
_owner = other._owner;
// done.
return *this;
}
inline char *ptr() const { return (char *)_ptr; }
inline char *data() const { return ((char *)_ptr+_b_offset); }
inline size_t bytesOffset() const { return _b_offset; }
inline size_t bytesLen() const { return _b_length; }
inline size_t storageSize() const { return _storage_size; }
inline bool isEmpty() const { return 0 == _ptr; }
void ref() const;
void unref();
inline int refCount() const { if (0 == _refcount) { return 0; } return (*_refcount); }
inline bool isUnused() const {
if (0 == _refcount) { return true; }
return (1 == (*_refcount));
}
protected:
char *_ptr;
size_t _storage_size;
size_t _b_offset;
size_t _b_length;
int *_refcount;
BufferOwner *_owner;
};
template <class T>
class Buffer: public RawBuffer
{
public:
Buffer() : RawBuffer(), _size(0) {
// pass...
}
Buffer(T *data, size_t size)
: RawBuffer((char *)data, 0, sizeof(T)*size), _size(size) {
// pass...
}
Buffer(size_t N, BufferOwner *owner=0)
: RawBuffer(N*sizeof(T), owner), _size(N) {
// pass...
}
Buffer(const Buffer<T> &other)
: RawBuffer(other), _size(other._size) {
// pass...
}
virtual ~Buffer() {
_size = 0;
}
explicit Buffer(const RawBuffer &other)
: RawBuffer(other), _size(_b_length/sizeof(T))
{
// pass
}
public:
const Buffer<T> &operator= (const Buffer<T> other) {
RawBuffer::operator =(other);
_size = other._size;
return *this;
}
inline bool operator<(const Buffer<T> &other) const {
// Comparison by pointer to data
return this->_ptr < other._ptr;
}
inline size_t size() const { return _size; }
inline T &operator[] (int idx) const {
#ifdef SDR_DEBUG
if ((idx >= _size) || (idx < 0)) {
RuntimeError err;
err << "Index " << idx << " out of bounds [0," << _size << ")";
throw err;
}
#endif
return reinterpret_cast<T *>(_ptr+_b_offset)[idx];
}
inline double norm2() const {
double nrm2 = 0;
for (size_t i=0; i<size(); i++) {
nrm2 += std::real(std::conj((*this)[i])*(*this)[i]);
}
return std::sqrt(nrm2);
}
inline double norm() const {
double nrm = 0;
for (size_t i=0; i<size(); i++) {
nrm += std::abs((*this)[i]);
}
return nrm;
}
inline double norm(double p) const {
double nrm = 0;
for (size_t i=0; i<size(); i++) {
nrm += std::pow(std::abs((*this)[i]), p);
}
return std::pow(nrm, 1./p);
}
inline Buffer<T> &operator *=(const T &a) {
for (size_t i=0; i<size(); i++) {
(*this)[i] *= a;
}
return *this;
}
inline Buffer<T> &operator /=(const T &a) {
for (size_t i=0; i<size(); i++) {
(*this)[i] /= a;
}
return *this;
}
template <class oT>
Buffer<oT> as() const {
return Buffer<oT>((const RawBuffer &)(*this));
}
inline Buffer<T> sub(size_t offset, size_t len) const {
if ((offset+len) > _size) { return Buffer<T>(); }
return Buffer<T>(RawBuffer(*this, offset*sizeof(T), len*sizeof(T)));
}
inline Buffer<T> head(size_t n) const {
if (n > _size) { return Buffer<T>(); }
return this->sub(0, n);
}
inline Buffer<T> tail(size_t n) const {
if (n > _size) { return Buffer<T>(); }
return this->sub(_size-n, n);
}
protected:
size_t _size;
};
template <class Scalar>
std::ostream &
operator<< (std::ostream &stream, const sdr::Buffer<Scalar> &buffer)
{
stream << "[";
if (10 < buffer.size()) {
stream << +buffer[0];
for (size_t i=1; i<5; i++) {
stream << ", " << +buffer[i];
}
stream << ", ..., " << +buffer[buffer.size()-6];
for (size_t i=1; i<5; i++) {
stream << ", " << +buffer[buffer.size()+i-6];
}
} else {
if (0 < buffer.size()) {
stream << +buffer[0];
for (size_t i=1; i<buffer.size(); i++) {
stream << ", " << +buffer[i];
}
}
}
stream << "]";
return stream;
}
template <class Scalar>
class BufferSet: public BufferOwner
{
public:
BufferSet(size_t N, size_t size)
: _bufferSize(size)
{
_free_buffers.reserve(N);
for (size_t i=0; i<N; i++) {
Buffer<Scalar> buffer(size, this);
_buffers[buffer.ptr()] = buffer;
_free_buffers.push_back(buffer.ptr());
}
}
virtual ~BufferSet() {
typename std::map<void *, Buffer<Scalar> >::iterator item = _buffers.begin();
for(; item != _buffers.end(); item++) {
item->second.unref();
}
_buffers.clear();
_free_buffers.clear();
}
inline bool hasBuffer() { return _free_buffers.size(); }
inline Buffer<Scalar> getBuffer() {
void *id = _free_buffers.back(); _free_buffers.pop_back();
return _buffers[id];
}
virtual void bufferUnused(const RawBuffer &buffer) {
// Add buffer to list of free buffers if they are still owned
if (0 != _buffers.count(buffer.ptr())) {
_free_buffers.push_back(buffer.ptr());
}
}
void resize(size_t numBuffers) {
if (_buffers.size() == numBuffers) { return; }
if (_buffers.size() < numBuffers) {
// add some buffers
size_t N = (numBuffers - _buffers.size());
for (size_t i=0; i<N; i++) {
Buffer<Scalar> buffer(_bufferSize, this);
_buffers[buffer.ptr()] = buffer;
}
}
}
protected:
size_t _bufferSize;
std::map<void *, Buffer<Scalar> > _buffers;
std::vector<void *> _free_buffers;
};
class RawRingBuffer: public RawBuffer
{
public:
RawRingBuffer();
RawRingBuffer(size_t size);
RawRingBuffer(const RawRingBuffer &other);
virtual ~RawRingBuffer();
inline const RawRingBuffer &operator=(const RawRingBuffer &other) {
RawBuffer::operator =(other);
_take_idx = other._take_idx;
_b_stored = other._b_stored;
return *this;
}
char &operator[] (int idx) {
#ifdef SDR_DEBUG
if ((idx < 0) || (idx>=(int)_b_stored)) {
RuntimeError err;
err << "RawRingBuffer: Index " << idx << " out of bounds [0," << bytesLen() << ").";
throw err;
}
#endif
int i = _take_idx+idx;
if (i >= (int)_storage_size) { i -= _storage_size; }
return *(ptr()+i);
}
inline size_t bytesLen() const { return _b_stored; }
inline size_t bytesFree() const {
return _storage_size-_b_stored;
}
inline bool put(const RawBuffer &src) {
// Data does not fit into ring buffer -> stop
if (src.bytesLen() > bytesFree()) { return false; }
// Obtain put_ptr
size_t put_idx = _take_idx+_b_stored;
if (put_idx > _storage_size) { put_idx -= _storage_size; }
// store data
if (_storage_size >= (put_idx+src.bytesLen())) {
// If the data can be copied directly
memcpy(_ptr+put_idx, src.data(), src.bytesLen());
_b_stored += src.bytesLen();
return true;
}
// If wrapped around -> Store first half
size_t num_a = _storage_size-put_idx;
memcpy(_ptr+put_idx, src.data(), num_a);
// store second half
memcpy(_ptr, src.data()+num_a, src.bytesLen()-num_a);
_b_stored += src.bytesLen();
return true;
}
inline bool take(const RawBuffer &dest, size_t N) {
// If there is not enough space in dest to store N bytes
if (N > dest.bytesLen()) { return false; }
// If there is not enough data available
if (N > bytesLen()) { return false; }
// If data can be taken at once
if (_storage_size > (_take_idx+N)) {
memcpy(dest.data(), _ptr+_take_idx, N);
_take_idx += N; _b_stored -= N;
return true;
}
// Copy in two steps
size_t num_a = _storage_size-_take_idx;
memcpy(dest.data(), _ptr+_take_idx, num_a);
memcpy(dest.data()+num_a, _ptr, N-num_a);
_take_idx = N-num_a; _b_stored -= N;
return true;
}
inline void drop(size_t N) {
N = std::min(N, bytesLen());
if (_storage_size>(_take_idx+N)) { _take_idx+=N; _b_stored -= N; }
else { _take_idx = N-(_storage_size-_take_idx); _b_stored -= N; }
}
inline void clear() { _take_idx = _b_stored = 0; }
inline void resize(size_t N) {
if (_storage_size == N) { return; }
_take_idx=_b_stored=0;
RawBuffer::operator =(RawBuffer(N));
}
protected:
size_t _take_idx;
size_t _b_stored;
};
template <class Scalar>
class RingBuffer: public RawRingBuffer
{
public:
RingBuffer() : RawRingBuffer(), _size(0), _stored(0) { }
RingBuffer(size_t N) : RawRingBuffer(N*sizeof(Scalar)), _size(N), _stored(0) { }
RingBuffer(const RingBuffer<Scalar> &other)
: RawRingBuffer(other), _size(other._size), _stored(other._stored) { }
virtual ~RingBuffer() { }
const RingBuffer<Scalar> &operator= (const RingBuffer<Scalar> &other) {
RawRingBuffer::operator =(other);
_size = other._size; _stored = other._stored;
return *this;
}
Scalar &operator[] (int idx) {
return reinterpret_cast<Scalar &>(RawRingBuffer::operator [](idx*sizeof(Scalar)));
}
inline size_t stored() const { return _stored; }
inline size_t free() const { return _size-_stored; }
inline size_t size() const { return _size; }
inline bool put(const Buffer<Scalar> &data) {
if (RawRingBuffer::put(data)) {
_stored += data.size(); return true;
}
return false;
}
inline bool take(const Buffer<Scalar> &dest, size_t N) {
if (RawRingBuffer::take(dest, N*sizeof(Scalar))) {
_stored -= N; return true;
}
return false;
}
inline void drop(size_t N) {
RawRingBuffer::drop(N*sizeof(Scalar)); _stored = _b_stored/sizeof(Scalar);
}
inline void resize(size_t N) {
RawRingBuffer::resize(N*sizeof(Scalar));
}
protected:
size_t _size;
size_t _stored;
};
}
#endif // __SDR_BUFFER_HH__
sdr::RawRingBuffer::RawRingBuffer
RawRingBuffer()
Empty constructor.
Definition: buffer.cc:84
sdr::Buffer::Buffer
Buffer(const RawBuffer &other)
Explicit type cast.
Definition: buffer.hh:143
sdr::RawBuffer::_b_offset
size_t _b_offset
Holds the offset of the buffer in bytes.
Definition: buffer.hh:98
sdr::Buffer::norm
double norm(double p) const
Returns the norm of the buffer.
Definition: buffer.hh:200
sdr::BufferSet::_free_buffers
std::vector< void * > _free_buffers
A vector of all unused buffers.
Definition: buffer.hh:351
sdr::Buffer::norm
double norm() const
Returns the norm of the buffer.
Definition: buffer.hh:191
sdr::RawBuffer
Base class of all buffers, represents an untyped array of bytes.
Definition: buffer.hh:32
sdr::RawRingBuffer::_take_idx
size_t _take_idx
The current read pointer.
Definition: buffer.hh:464
sdr::RingBuffer::operator=
const RingBuffer< Scalar > & operator=(const RingBuffer< Scalar > &other)
Assigment operator, turns this buffer into a reference to the other ring buffer.
Definition: buffer.hh:490
sdr::RingBuffer::_stored
size_t _stored
The number of stored elements.
Definition: buffer.hh:540
sdr::RawRingBuffer::~RawRingBuffer
virtual ~RawRingBuffer()
Destructor.
Definition: buffer.cc:102
sdr::Buffer::Buffer
Buffer()
Empty constructor.
Definition: buffer.hh:115
sdr::BufferOwner::bufferUnused
virtual void bufferUnused(const RawBuffer &buffer)=0
Gets called once an owned buffer gets unused.
sdr::Buffer::operator/=
Buffer< T > & operator/=(const T &a)
In-place, element wise division of the buffer with the scalar a.
Definition: buffer.hh:217
sdr::Buffer::as
Buffer< oT > as() const
Explicit type cast.
Definition: buffer.hh:226
sdr::RawRingBuffer::bytesFree
size_t bytesFree() const
Returns the number of free bytes in the ring buffer.
Definition: buffer.hh:395
sdr::RingBuffer
A simple typed ring-buffer.
Definition: buffer.hh:473
sdr::RingBuffer::~RingBuffer
virtual ~RingBuffer()
Destructor.
Definition: buffer.hh:487
sdr::RawRingBuffer::bytesLen
size_t bytesLen() const
Returns the number of bytes available for reading.
Definition: buffer.hh:392
sdr::RawRingBuffer::clear
void clear()
Clear the ring-buffer.
Definition: buffer.hh:453
sdr::RawBuffer::ref
void ref() const
Increment reference counter.
Definition: buffer.cc:57
sdr::RingBuffer::stored
size_t stored() const
Returns the number of stored elements.
Definition: buffer.hh:502
sdr
Definition: autocast.hh:8
sdr::RawRingBuffer::take
bool take(const RawBuffer &dest, size_t N)
Take N bytes from the ring buffer and store it into the given buffer dest.
Definition: buffer.hh:426
sdr::RawBuffer::isEmpty
bool isEmpty() const
Returns true if the buffer is invalid/empty.
Definition: buffer.hh:77
sdr::RawBuffer::storageSize
size_t storageSize() const
Returns the raw buffer size in bytes.
Definition: buffer.hh:75
sdr::BufferSet::BufferSet
BufferSet(size_t N, size_t size)
Preallocates N buffers of size size.
Definition: buffer.hh:292
sdr::Buffer::operator[]
T & operator[](int idx) const
Element access.
Definition: buffer.hh:170
sdr::RawBuffer::refCount
int refCount() const
Returns the reference counter.
Definition: buffer.hh:84
sdr::RawBuffer::_owner
BufferOwner * _owner
Holds a weak reference the buffer owner.
Definition: buffer.hh:104
sdr::RingBuffer::size
size_t size() const
Returns the size of the ring buffer.
Definition: buffer.hh:506
sdr::Buffer::~Buffer
virtual ~Buffer()
Destructor.
Definition: buffer.hh:138
sdr::RawBuffer::_b_length
size_t _b_length
Holds the length of the buffer (view) in bytes.
Definition: buffer.hh:100
sdr::RuntimeError
The runtime error class.
Definition: exception.hh:36
sdr::RingBuffer::resize
void resize(size_t N)
Resizes the ring buffer to N elements.
Definition: buffer.hh:532
sdr::BufferSet::_bufferSize
size_t _bufferSize
Size of each buffer.
Definition: buffer.hh:346
sdr::Buffer::size
size_t size() const
Returns the number of elements of type T in this buffer.
Definition: buffer.hh:166
sdr::BufferSet
A set of buffers, that tracks their usage.
Definition: buffer.hh:288
sdr::RawRingBuffer::operator[]
char & operator[](int idx)
Element access.
Definition: buffer.hh:378
sdr::RawBuffer::bytesLen
size_t bytesLen() const
Returns the size of the buffer by the view.
Definition: buffer.hh:73
sdr::Buffer::Buffer
Buffer(size_t N, BufferOwner *owner=0)
Creates a buffer with N samples.
Definition: buffer.hh:126
sdr::RawRingBuffer
A simple ring buffer.
Definition: buffer.hh:356
sdr::RawBuffer::data
char * data() const
Returns the pointer to the data of the buffer view.
Definition: buffer.hh:69
sdr::RawRingBuffer::drop
void drop(size_t N)
Drops at most N bytes from the buffer.
Definition: buffer.hh:446
sdr::RingBuffer::RingBuffer
RingBuffer(const RingBuffer< Scalar > &other)
Copy constructor, creates a reference to the other ring buffer.
Definition: buffer.hh:483
sdr::Buffer::Buffer
Buffer(const Buffer< T > &other)
Create a new reference to the buffer.
Definition: buffer.hh:132
sdr::RingBuffer::RingBuffer
RingBuffer(size_t N)
Constructs a ring buffer of size N.
Definition: buffer.hh:480
sdr::RingBuffer::take
bool take(const Buffer< Scalar > &dest, size_t N)
Takes N elements from the buffer and stores them into dest.
Definition: buffer.hh:519
sdr::Buffer::tail
Buffer< T > tail(size_t n) const
Returns a new view on this buffer.
Definition: buffer.hh:243
sdr::Buffer::norm2
double norm2() const
Returns the norm of the buffer.
Definition: buffer.hh:182
sdr::Buffer::head
Buffer< T > head(size_t n) const
Returns a new view on this buffer.
Definition: buffer.hh:237
sdr::RawBuffer::RawBuffer
RawBuffer()
Constructs an empty buffer.
Definition: buffer.cc:10
sdr::BufferSet::bufferUnused
virtual void bufferUnused(const RawBuffer &buffer)
Callback gets called once the buffer gets unused.
Definition: buffer.hh:324
sdr::RawBuffer::_storage_size
size_t _storage_size
Holds the size of the buffer in bytes.
Definition: buffer.hh:96
sdr::BufferSet::hasBuffer
bool hasBuffer()
Returns true if there is a free buffer.
Definition: buffer.hh:315
sdr::RawRingBuffer::operator=
const RawRingBuffer & operator=(const RawRingBuffer &other)
Assignment operator, turns this ring buffer into a reference to the other one.
Definition: buffer.hh:370
sdr::RingBuffer::RingBuffer
RingBuffer()
Empty constructor.
Definition: buffer.hh:477
sdr::RingBuffer::free
size_t free() const
Returns the number of free elements.
Definition: buffer.hh:504
sdr::RingBuffer::_size
size_t _size
The size of the ring buffer.
Definition: buffer.hh:538
sdr::RawBuffer::_ptr
char * _ptr
Holds the pointer to the data or 0, if buffer is empty.
Definition: buffer.hh:94
sdr::BufferSet::_buffers
std::map< void *, Buffer< Scalar > > _buffers
Holds a reference to each buffer of the buffer set, referenced by the data pointer of the buffer...
Definition: buffer.hh:349
sdr::RawBuffer::bytesOffset
size_t bytesOffset() const
Returns the offset of the data by the view.
Definition: buffer.hh:71
sdr::Buffer::operator=
const Buffer< T > & operator=(const Buffer< T > other)
Assignment operator, turns this buffer into a reference to the other buffer.
Definition: buffer.hh:152
sdr::BufferSet::resize
void resize(size_t numBuffers)
Resize the buffer set.
Definition: buffer.hh:332
sdr::Buffer::operator*=
Buffer< T > & operator*=(const T &a)
In-place, element wise product of the buffer with the scalar a.
Definition: buffer.hh:209
sdr::RingBuffer::put
bool put(const Buffer< Scalar > &data)
Puts the given elements into the ring buffer.
Definition: buffer.hh:510
sdr::Buffer::sub
Buffer< T > sub(size_t offset, size_t len) const
Returns a new view on this buffer.
Definition: buffer.hh:231
sdr::RawRingBuffer::_b_stored
size_t _b_stored
Offset of the write pointer relative to the _take_idx ptr, such that the number of stored bytes is _b...
Definition: buffer.hh:467
sdr::RawBuffer::ptr
char * ptr() const
Returns the pointer to the data (w/o view).
Definition: buffer.hh:67
sdr::RawBuffer::operator=
const RawBuffer & operator=(const RawBuffer &other)
Assignment.
Definition: buffer.hh:54
sdr::BufferOwner
Abstract class (interface) of a buffer owner.
Definition: buffer.hh:24
sdr::RawBuffer::unref
void unref()
Dereferences the buffer.
Definition: buffer.cc:63
sdr::RawBuffer::isUnused
bool isUnused() const
We assume here that buffers are owned by one object: A buffer is therefore "unused" if the owner hold...
Definition: buffer.hh:87
sdr::RingBuffer::drop
void drop(size_t N)
Drops N elements from the ring buffer.
Definition: buffer.hh:527
sdr::RawBuffer::_refcount
int * _refcount
The reference counter.
Definition: buffer.hh:102
sdr::RawBuffer::~RawBuffer
virtual ~RawBuffer()
Destructor.
Definition: buffer.cc:51
sdr::BufferSet::getBuffer
Buffer< Scalar > getBuffer()
Obtains a free buffer.
Definition: buffer.hh:318
sdr::RawRingBuffer::put
bool put(const RawBuffer &src)
Puts the given data into the ring-buffer.
Definition: buffer.hh:401
sdr::Buffer::_size
size_t _size
Holds the number of elements of type T in the buffer.
Definition: buffer.hh:250
sdr::RawRingBuffer::resize
void resize(size_t N)
Resizes the ring buffer.
Definition: buffer.hh:456
sdr::Buffer
A typed buffer.
Definition: buffer.hh:111
sdr::BufferSet::~BufferSet
virtual ~BufferSet()
Destructor, unreferences all buffers.
Definition: buffer.hh:305
sdr::RingBuffer::operator[]
Scalar & operator[](int idx)
Element access.
Definition: buffer.hh:497
sdr::Buffer::Buffer
Buffer(T *data, size_t size)
Constructor from raw data.
Definition: buffer.hh:120