/** @file vrefcounted.h
*	Implementation for an abstract refcounted object
*	@author Chris Burns (cburns@ea.com)
*
*	(c) 2012 Electronic Arts Inc.
*/

#ifndef EABASETYPESPLUS_VREFCOUNTED_H_
#define EABASETYPESPLUS_VREFCOUNTED_H_

namespace EA
{
namespace Types
{
	/*! @class	VRefCounted refcountedica.h "ux_base/refcountedica.h"
	*	@brief	Mixin implementation of refcounting for IRefCounted
	*/
	template<typename Base>
	class VRefCounted : public Base
	{
	public:

		VRefCounted();

		/*!
		*	Add a reference to this object
		*	@return	int	The new reference count
		*/
		inline virtual int AddRef();

		/*!
		*	Release a reference to this object
		*	@return	int	The new reference count
		*/
		inline virtual int Release();

		/*!
		*	Get the current reference count
		*	@return	int	The current reference count
		*/
		inline virtual int GetRefCount() const;

	protected:

		int mRefCount;
	};

	/*! @class	VRefCounted refcountedica.h "ux_base/refcountedica.h"
	*	@brief	Mixin implementation of refcounting for IRefCounted with two base classes
	*/
	template<typename Base1, typename Base2>
	class VRefCounted2 : public Base1, public Base2
	{
	public:

		VRefCounted2();

		/*!
		*	Add a reference to this object
		*	@return	int	The new reference count
		*/
		inline virtual int AddRef();

		/*!
		*	Release a reference to this object
		*	@return	int	The new reference count
		*/
		inline virtual int Release();

		/*!
		*	Get the current reference count
		*	@return	int	The current reference count
		*/
		inline virtual int GetRefCount() const;

	protected:

		int mRefCount;
	};

	template<typename Base>
	VRefCounted<Base>::VRefCounted():
		Base(),
		mRefCount(1)
	{
	}

	template<typename Base>
	/* inline virtual */ int VRefCounted<Base>::AddRef()
	{
		return ++mRefCount;
	}

	template<typename Base>
	/* inline virtual */ int VRefCounted<Base>::Release()
	{
		if(--mRefCount <= 0)
		{
			this->DeleteThis();
			return 0;
		}
		else
		{
			return mRefCount;
		}
	}

	template<typename Base>
	/* inline virtual */ int VRefCounted<Base>::GetRefCount() const
	{
		return mRefCount;
	}

	template<typename Base1, typename Base2>
	VRefCounted2<Base1, Base2>::VRefCounted2():
		Base1(),
		Base2(),
		mRefCount(1)
	{
	}

	template<typename Base1, typename Base2>
	/* inline virtual */ int VRefCounted2<Base1, Base2>::AddRef()
	{
		return ++mRefCount;
	}

	template<typename Base1, typename Base2>
	/* inline virtual */ int VRefCounted2<Base1, Base2>::Release()
	{
		if(--mRefCount <= 0)
		{
			this->DeleteThis();
			return 0;
		}
		else
		{
			return mRefCount;
		}
	}

	template<typename Base1, typename Base2>
	/* inline virtual */ int VRefCounted2<Base1, Base2>::GetRefCount() const
	{
		return mRefCount;
	}
}
}

#endif /* EABASETYPESPLUS_VREFCOUNTED_H_ */
