//-----------------------------------------------------------------------------
//
//  Ref.h
//
//  Reference counting for objects.
//
//	Copyright (c) 2010 Mal Lansell <mal@lansell.org>
//	All rights reserved.
//
//	SOFTWARE NOTICE AND LICENSE
//
//	This file is part of OpenZWave.
//
//	OpenZWave is free software: you can redistribute it and/or modify
//	it under the terms of the GNU Lesser General Public License as published
//	by the Free Software Foundation, either version 3 of the License,
//	or (at your option) any later version.
//
//	OpenZWave is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU Lesser General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public License
//	along with OpenZWave.  If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#ifndef _Ref_H
#define _Ref_H

#pragma once

#include "Defs.h"

namespace OpenZWave
{
	namespace Internal
	{
		namespace Platform
		{
			/**
			 * Provides reference counting for objects.
			 * Any class wishing to include reference counting should be derived from Ref.
			 * Derived classes must declare their destructor as protected virtual.
			 * On construction, the reference count is set to one.  Calls to AddRef increment 
			 * the count.  Calls to Release decrement the count.  When the count reaches
			 * zero, the object is deleted.
			 * \ingroup Platform
			 */
			class Ref
			{
				public:
					/**
					 * Initializes the RefCount to one.  The object
					 * can only be deleted through a call to Release.
					 * \see AddRef, Release
					 */
					Ref()
					{
						m_refs = 1;
					}

					/**
					 * Increases the reference count of the object.
					 * Every call to AddRef requires a matching call
					 * to Release before the object will be deleted.
					 * \see Release
					 */
					void AddRef()
					{
						++m_refs;
					}

					/**
					 * Removes a reference to an object.
					 * If this was the last reference to the message, the 
					 * object is deleted.
					 * \see AddRef
					 */
					int32 Release()
					{
						if (0 >= (--m_refs))
						{
							delete this;
							return 0;
						}
						return m_refs;
					}

				protected:
					virtual ~Ref()
					{
					}

				private:
					// Reference counting
					int32 m_refs;

			};
		// class Ref
		}// namespace Platform
	} // namespace Internal
} // namespace OpenZWave

#endif // _Ref_H

