/* +---------------------------------------------------------------------------+
   |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
   |                                                                           |
   |                   http://mrpt.sourceforge.net/                            |
   |                                                                           |
   |   Copyright (C) 2005-2008  University of Malaga                           |
   |                                                                           |
   |    This software was written by the Perception and Robotics               |
   |      research group, University of Malaga (Spain).                        |
   |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
   |                                                                           |
   |  This file is part of the MRPT project.                                   |
   |                                                                           |
   |     MRPT is free software: you can redistribute it and/or modify          |
   |     it under the terms of the GNU General Public License as published by  |
   |     the Free Software Foundation, either version 3 of the License, or     |
   |     (at your option) any later version.                                   |
   |                                                                           |
   |   MRPT 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 General Public License for more details.                          |
   |                                                                           |
   |     You should have received a copy of the GNU General Public License     |
   |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
   |                                                                           |
   +---------------------------------------------------------------------------+ */
#ifndef  CReferencedMemBlock_H
#define  CReferencedMemBlock_H

#include <MRPT/UTILS/utils_defs.h>

#include <utility>

namespace UTILS
{
	/** Represents a memory block (via "void*") that can be shared between several objects through copy operator (=).
	  *  It keeps the reference count and only when it comes to zero, the memory block is really freed.
	  */
	class CReferencedMemBlock
	{
	public:
		typedef std::pair<unsigned, void*>  TRefPointer;

		CReferencedMemBlock();
		CReferencedMemBlock(const CReferencedMemBlock& o);
		CReferencedMemBlock & operator =(const CReferencedMemBlock& o);
		
		/** Destructor, calls dereference_once. */
		virtual ~CReferencedMemBlock();

		/** Dereference current pointer and create a new one of a given size, through "calloc" */
		void calloc(const size_t &nBytes);

		/** Return the current number of references to the object: If it is 1, after freeing this object the memory block will be deallocated as well. */
		unsigned refCount() const;

		void *get() { return m_data->second; }
		const void *get() const { return m_data->second; }

		template <class T> T getAs() { return static_cast<T>(m_data->second); }
		template <class T> const T getAs() const { return static_cast<T>(m_data->second); }

	protected:
		TRefPointer   *m_data;

		/** Decrease reference count of current pointer, and set current to NULL, freeing memory if count comes to zero. */
		void dereference_once();

	}; // End of class

} // End of namespace

#endif
