/*==================================================================================================
	CAMutex.h
	
	$Log: CAMutex.h,v $
	Revision 1.4  2004/10/28 01:11:58  dwyatt
	[a radar for each of our projects] CAMutex.cpp (not .h) requires errno.h
	
	Revision 1.3  2004/10/28 00:14:21  ealdrich
	Radar 3855797: Add include of errno.h to mac os builds
	
	Revision 1.2  2004/08/26 08:13:33  jcm10
	finish bring up on Windows
	
	Revision 1.1  2003/12/17 20:56:59  dwyatt
	new base class for CAGuard
	
	created Wed Dec 17 2003, Doug Wyatt
	Copyright (c) 2003 Apple Computer, Inc.  All Rights Reserved

	$NoKeywords: $
==================================================================================================*/

#ifndef __CAMutex_h__
#define __CAMutex_h__

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

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

#if TARGET_OS_MAC
	#include <pthread.h>
#elif TARGET_OS_WIN32
	#include <windows.h>
#else
	#error	Unsupported operating system
#endif

//==================================================================================================
//	A recursive mutex.
//==================================================================================================

class	CAMutex
{
//	Construction/Destruction
public:
					CAMutex(const char* inName);
	virtual			~CAMutex();

//	Actions
public:
	virtual bool	Lock();
	virtual void	Unlock();
	virtual bool	Try(bool& outWasLocked);	// returns true if lock is free, false if not
		
//	Implementation
protected:
	const char*		mName;
#if TARGET_OS_MAC
	pthread_t		mOwner;
	pthread_mutex_t	mMutex;
#elif TARGET_OS_WIN32
	UInt32			mOwner;
	HANDLE			mMutex;
#endif

//	Helper class to manage taking and releasing recursively
public:
	class			Locker
	{
	
	//	Construction/Destruction
	public:
					Locker(CAMutex& inMutex) : mMutex(inMutex), mNeedsRelease(false) { mNeedsRelease = mMutex.Lock(); }
					~Locker() { if(mNeedsRelease) { mMutex.Unlock(); } }
	
	private:
					Locker(const Locker&);
		Locker&		operator=(const Locker&);
	
	//	Implementation
	private:
		CAMutex&	mMutex;
		bool		mNeedsRelease;
	
	};
};


#endif // __CAMutex_h__
