/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef __NRINGBUFFER__
#define	__NRINGBUFFER__


		#include "container/narray.h"


namespace GS {

/*
	@short	Ring buffer.
	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
template <class T> class RingBuffer
{
		Array <T> buffer;
		uint		put, get, usage;

public:

		/// Get the maximum number of element in buffer.
		uint		GetCount() const
		{	return buffer.GetCount();	}

		/// Number of T left to put in the buffer.
		uint		GetFree() const
		{	return buffer.GetCount() - usage;	}
		/// Number of T available to get from the buffer.
		uint		GetUsage() const
		{	return usage;	}

		/// Increment the put pointer, returns true when successful.
		bool		Produce()
		{
			if	(usage == buffer.GetCount())
				return false;

			put = (put + 1) % buffer.GetCount();
			usage++;

			return true;
		}
		/// Increment the get pointer, returns true when successful.
		bool		Consume()
		{
			if	(usage == 0)
				return false;

			get = (get + 1) % buffer.GetCount();
			usage--;

			return true;
		}

		/// Retrieve the object at the current get pointer.
		T			&CurrentGet()
		{	return buffer[get];	}
		/// Retrieve the object at the current put pointer.
		T			&CurrentPut()
		{	return buffer[put];	}

		bool		Allocate(uint count)
		{
			put = get = usage = 0;
			return buffer.Allocate(count);
		}

		RingBuffer() : put(0), get(0), usage(0) {}
};

} // GS


#endif	// __NRINGBUFFER__
