/* 
 * File:   ReceiverBuffer.hpp
 * Author: jens
 *
 * Created on 22. Dezember 2014, 15:47
 */

#ifndef RECEIVERBUFFER_HPP
#define	RECEIVERBUFFER_HPP

#include <cpp/radio/Vector.hpp>

using namespace Radio;


template <uint32_t numBuffers>
class RxBuffer
{
public:	
	RxBuffer(uint32_t size=0)
	: m_pT(nullptr)
	, m_size(size)
	{
		resize(size);
	}

	~RxBuffer()
	{
	}

	void write(RVec const &data, uint32_t len)
	{
		if (m_numfill.get() >= numBuffers)
			return;

		m_buffers[m_w++] = data;

		if (m_w >= numBuffers)
			m_w = 0;

		m_numfill += 1;
		
		if (m_pT)
			m_pT->notify();
	}

	const RVec& read()
	{
		uint32_t index;
		m_pT = Thread::getCurrentThread();

		while (m_numfill.get() == 0)
		{
			m_pT->wait(100);
			if (m_pT->threadShouldExit())
				return m_buffers[0];
		}
		
		index = m_r++;
		if (m_r >= numBuffers)
			m_r = 0;

		m_numfill -= 1;

		return m_buffers[index];
	}

	void resize(uint32_t size)
	{
		for (int i=0; i < numBuffers; i++)
		{
			m_buffers[i].resize(size);
		}
		
		m_r = 0;
		m_w = 0;
		m_size = size;
		m_numfill = 0;
	}

private:
	Thread *m_pT;
	Atomic<uint32_t> m_numfill;
	RVec m_buffers[numBuffers];
	uint32_t m_size;
	uint32_t m_r;
	uint32_t m_w;
};


#endif	/* RECEIVERBUFFER_HPP */

