File mudaq_circular_buffer.hpp

File List > libmudaq > mudaq_circular_buffer.hpp

Go to the documentation of this file

#ifndef __MUDAQ_CIRCULAR_BUFFER_HPP_QKI1IAR0__
#define __MUDAQ_CIRCULAR_BUFFER_HPP_QKI1IAR0__

#include <ostream>
#include <type_traits>
#include <vector>

#include <cstdint>

namespace mudaq {

  template<unsigned BUFFER_ORDER, typename T = uint32_t>
  class CircularSubBufferProxy
  {
  public:
    static const size_t BUFFER_SIZE = (1 << BUFFER_ORDER);
    static const size_t BUFFER_MASK = (BUFFER_SIZE - 1);

    CircularSubBufferProxy() : _base(nullptr), _offset(0), _size(0) {}
    CircularSubBufferProxy(volatile void* base, size_t offset, size_t size) :
      _base(static_cast<volatile T*>(base)), _offset(offset), _size(size) {}

    bool operator!() const { return (_base == nullptr); }
    T operator[](size_t idx) const
    {
      return _base[(_offset + idx) & BUFFER_MASK];
    }
    bool empty() const { return (_size == 0); }
    size_t size() const { return _size; }
    uint32_t give_offset() const {
      return _offset;
    }
    uint32_t give_end() const {
      return ( (_offset + _size - 1) & BUFFER_MASK );
    }

  private:
    volatile T* _base;
    size_t _offset;
    size_t _size;

    friend std::ostream& operator<<(std::ostream & os,
                                    const CircularSubBufferProxy& sub)
    {
      os << "CircularSubBufferProxy(";
      if (!sub) {
        os << "INVALID)";
      } else {
        os << "base=" << sub._base << ", "
           << "offset=" << sub._offset << ", "
           << "size=" << sub.size() << ")";
      }
    return os;
    }
  };

  template<unsigned O, typename T = uint32_t>
  class CircularBufferProxy
  {
  public:
    static const size_t BUFFER_ORDER = O;
    static const size_t BUFFER_SIZE = (1 << BUFFER_ORDER);
    static const size_t BUFFER_MASK = (BUFFER_SIZE - 1);

    typedef CircularSubBufferProxy<BUFFER_ORDER, T> SubBuffer;

    CircularBufferProxy() : _base(nullptr) {}
    CircularBufferProxy(void* base) : _base(static_cast<T*>(base)) {}

    bool operator!() const { return (_base == nullptr); }
    T operator[](size_t idx) const { return _base[idx & BUFFER_MASK]; }
    bool empty() const { return (BUFFER_SIZE == 0); }
    size_t size() const { return BUFFER_SIZE; }
    SubBuffer sub_buffer(size_t offset, size_t size) const
    {
      return SubBuffer(_base, offset, size);
    }

  private:
    T* _base;

    friend std::ostream& operator<<(std::ostream & os,
                                    const CircularBufferProxy& buf)
    {
        os << "CircularBufferProxy(";
        if (!buf) {
            os << "INVALID)";
        } else {
            os << "base=" << buf._base << ", "
               << "order=" << buf.BUFFER_ORDER << ", "
               << "size=" << buf.size() << ")";
        }
        return os;
    }
  };

  template<unsigned O, typename T = uint32_t>
  class CircularBuffer : public CircularBufferProxy<O, T>
  {
  public:
    typedef CircularBufferProxy<O, T> Base;
    CircularBuffer() : _data(Base::BUFFER_SIZE, 0), Base(_data.data()) {}

  private:
    std::vector<T> _data;
  };

} // namespace mudaq

#endif // __MUDAQ_CIRCULAR_BUFFER_HPP_QKI1IAR0__