/****************************************************************************************

		MCCountedObject.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	 Greg
		Date:	 5/26/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		11/11/99	Charles		Inlined Add and Release for speed
		2/22/99		Ian			Added static Create() functions.
		9/9/98		Ian			fRefCount, and fReachedZero are public under the debug
								version, slightly evil, but much better than the alternative.
		9/1/98		Thierry		added some debug code to find the leaks in the CountedObjects
		6/3/98		Greg		Made both objects subclass from IMCUnknown so that
								we can guarantee their position in the vtbl for
								TMCCountedPtr
		6/2/98		Greg		Made AddRef() and Release() virtual MCCOMAPI calls
								(since some subclasses are COM classes that override
								these calls)

*****************************************************************************************/

#ifndef __MCCOUNTEDOBJECT__
#define __MCCOUNTEDOBJECT__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCCompiler.h"
#include "MCBasicTypes.h"
#include "MCCompObj.h"

/// \addtogroup MCCore
/// \{

///	<P>Counted objects are objects that use a counter to keep track of how many other objects need them, 
/// and delete themselves when nobody needs them anymore. A counted object has an AddRef method that increments its counter, 
/// and a Release method that decrements it. When the value of the counter reaches zero, the object is deleted.</P>
///
/// Take a look at TMCCountedCreateHelper to see how to create and return a counted object
///
/// \note If your object can be accessed by two threads at the same time, you ought to derive it from TMCSMPCountedObject
/// (it uses an atomic counter).
///
class TMCCountedObject : public IMCUnknown
{
	public:
	
		// we cannot use TMCObject because of problem with CW8 for TransPoser ! (Charles 05/18/2005)
		void*	operator new			(MCSize byteCount) throw();
		void	operator delete			(void* block);
		void*	operator new[]			(MCSize byteCount) throw();
		void	operator delete[]		(void* block);

	public:
		static void Create(TMCCountedObject** outObject);

	protected:
		TMCCountedObject(void); // Sets ref count to ONE now (Charles)

		virtual ~TMCCountedObject();
		
	public:
	
		virtual MCErr	MCCOMAPI QueryInterface	(const MCIID& riid, void** ppvObj);
		virtual uint32	MCCOMAPI AddRef			();
		virtual uint32	MCCOMAPI Release		();
	
	protected:
	
#if !Debug_
		uint32	fRefCount;

#else
	public:
		uint32				fRefCount;

		uint32				fUniqueObjectNumber;
		TMCCountedObject*	fPreviousCountedObject; // to chain every objects existing at one given instant
		TMCCountedObject*	fNextCountedObject;
#endif

};

/// \}

inline uint32 TMCCountedObject::AddRef()
{
	return ++fRefCount;
}

inline uint32 TMCCountedObject::Release()
{
	uint32 unreleasedCount = 0;

	unreleasedCount = --fRefCount;

	if (unreleasedCount == 0)
	{
		delete this;
	}
	return unreleasedCount;
}



#endif