/*=============================================================================
	CATokenMap.h

	$Log: CATokenMap.h,v $
	Revision 1.6  2004/04/13 07:06:52  jcm10
	fix compiler warnings
	
	Revision 1.5  2004/03/24 23:49:59  jcm10
	add a mutex to guard the token map
	
	Revision 1.4  2003/12/19 01:40:26  jcm10
	fix compile problem
	
	Revision 1.3  2003/12/11 02:08:45  jcm10
	add UnmapObject
	
	Revision 1.2  2003/11/20 22:56:53  dwyatt
	__COREAUDIO_USE_FLAT_INCLUDES__
	
	Revision 1.1  2003/02/17 20:37:33  jcm10
	moved here from AudioHardware/Utility
	
	Revision 1.1  2002/03/01 02:05:44  jcm10
	moved here from ../../Utility
	
	Revision 1.6  2002/02/16 02:02:43  jcm10
	left off one typename
	
	Revision 1.5  2002/02/15 02:31:59  jcm10
	remove the hack around for gcc3 warning
	
	Revision 1.4  2002/02/14 23:30:32  jcm10
	clean up for gcc3
	
	Revision 1.3  2001/11/15 02:06:25  jcm10
	move the declaration of TokenMap to make cpp-precomp happy
	
	Revision 1.2  2001/06/06 00:40:27  jcm10
	fix the inifinite loop in GetToken()
	
	Revision 1.1  2001/06/05 01:54:49  jcm10
	first checked in
	
	Revision 0.0  Fri Jun 01 2001  moorf
	created
		
	$NoKeywords: $
=============================================================================*/
#if !defined(__CATokenMap_h__)
#define __CATokenMap_h__

//=============================================================================
//	Includes
//=============================================================================

//  System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
	#include <CoreAudio/CoreAudioTypes.h>
#else
	#include <CoreAudioTypes.h>
#endif

//  PublicUtility Includes
#include "CAMutex.h"

//  Standard Library Includes
#include <map>
#include <iterator>

//=============================================================================
//	CATokenMap
//=============================================================================

template <class T>
class	CATokenMap
{

//	Types
private:
	typedef std::map<UInt32, T*>	TokenMap;

//	Construction/Destruction
public:
			CATokenMap() : mTokenMap(), mNextToken(256), mTokenMapMutex("CATokenMap Mutex") {}
			~CATokenMap() {}

//	Operations
public:
	UInt32	GetToken(T* inObject) const
	{
		CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
		UInt32 theAnswer = 0;
		typename TokenMap::const_iterator i = mTokenMap.begin();
		while((theAnswer == 0) && (i != mTokenMap.end()))
		{
			if(i->second == inObject)
			{
				theAnswer = i->first;
			}
			std::advance(i, 1);
		}
		return theAnswer;
	}
	
	T*		GetObject(UInt32 inToken) const
	{
		CAMutex::Locker theLocker(const_cast<CAMutex&>(mTokenMapMutex));
		typename TokenMap::const_iterator i = mTokenMap.find(inToken);
		return i != mTokenMap.end() ? i->second : NULL;
	}

	void	AddMapping(UInt32 inToken, T* inObject)
	{
		CAMutex::Locker theLocker(mTokenMapMutex);
		typename TokenMap::iterator i = mTokenMap.find(inToken);
		if(i != mTokenMap.end())
		{
			i->second = inObject;
		}
		else
		{
			mTokenMap.insert(typename TokenMap::value_type(inToken, inObject));
		}
	}
	
	void	RemoveMapping(UInt32 inToken, T* /*inObject*/)
	{
		CAMutex::Locker theLocker(mTokenMapMutex);
		typename TokenMap::iterator i = mTokenMap.find(inToken);
		if(i != mTokenMap.end())
		{
			mTokenMap.erase(i);
		}
	}
	
	UInt32	GetNextToken()
	{
		return mNextToken++;
	}
	
	UInt32	MapObject(T* inObject)
	{
		CAMutex::Locker theLocker(mTokenMapMutex);
		UInt32 theToken = GetNextToken();
		mTokenMap.insert(typename TokenMap::value_type(theToken, inObject));
		return theToken;
	}
	
	void	UnmapObject(T* inObject)
	{
		CAMutex::Locker theLocker(mTokenMapMutex);
		bool isDone = false;
		typename TokenMap::iterator i = mTokenMap.begin();
		while(!isDone && (i != mTokenMap.end()))
		{
			if(i->second == inObject)
			{
				mTokenMap.erase(i);
				isDone = true;
			}
			else
			{
				std::advance(i, 1);
			}
		}
	}

//	Implementation
private:	
	TokenMap	mTokenMap;
	UInt32		mNextToken;
	CAMutex		mTokenMapMutex;

};

#endif
