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


		MCSMPCriticalSection.h

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

		Author:	Emil
		Date:	3/27/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		10/18/99	Yann		SetAtomicCounterValue was returning an int32 on the Mac
		7/29/99		Eml			Atomic Counter fix
		6/10/99		Ian			Array API changes.
		04/23/99	Eml/scooper	stub MakeSMPProcess
		4/22/99		Eml			Reverted to old TLS mechanism. New one could not work on the Mac
		5/27/98		Eml			include MCOSConfig.h

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

#ifndef __MCSMPCriticalSection__
#define __MCSMPCriticalSection__

#include "MCBasicDefines.h"
#include "MCBasicTypes.h"
#include "MCOSConfig.h"
#include "MCCompiler.h"


class TMCCriticalSection;


#ifdef qSMP


TMCCriticalSection * NewCS();
void DeleteCS(TMCCriticalSection * aCS);
void EnterCS(TMCCriticalSection * aCS);
void LeaveCS(TMCCriticalSection * aCS);


#else // if qSMP

#error "You must define qSMP !!!"

/*
//Stubbed definitions of SMP calls when qSMP is not defined

//typedef int32 TMCCriticalSection;

#define NewCS() nil
#define DeleteCS(x)
#define EnterCS(x)
#define LeaveCS(x)

*/
#endif


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// General Tools useful with SMP
//
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

/// \addtogroup MCCore
/// \{

// ****************************************************************************
//							CWhileInCS	
// 
/// This class should be used to declare a local variable. The life span of this
/// variable determines what block of code is encapsulated in the critical section.
/// For more information on critical region see TMCCriticalSection.
///
/// <P>One of the advantage of using a local variable is that the destructor is
/// called if an exception is thrown or if return is called in the middle of the
/// function</P>
///
/// <P>For instance, you could write:</P>
///
/// \code
/// {
///   CWhileInCS cs(criticalSection);
///
///   // Code excuted inside the critical section
///   ...
/// }
/// // Code excuted outside the critical section
/// ...
/// \endcode
///
class CWhileInCS : public TMCObject
{
	public:
		CWhileInCS(TMCCriticalSection * theCS) { fCS=theCS; if (fCS) EnterCS(fCS); }
		~CWhileInCS() {Clean();}
		void Clean() {if (fCS) {LeaveCS(fCS);} fCS = nil;}

	protected:
		TMCCriticalSection * fCS;
};
/// \}


// ****************************************************************************
//							CWhileInConditionalCS	
//
/// Use CWhileInCS instead.
///
class CWhileInConditionalCS : public TMCObject
{
	public:
		CWhileInConditionalCS(TMCCriticalSection * theCS) : fCS(theCS),fLocked(false) {}
		~CWhileInConditionalCS() { 	Clean(); }
		boolean Cond(boolean *cond) {EnterCS(fCS); fLocked = true; return *cond;}
		boolean Cond(void **cond) {EnterCS(fCS); fLocked = true; return (*cond) != nil;}
		void Clean() {if (fLocked) {LeaveCS(fCS);} fLocked = false;}

	protected:
		TMCCriticalSection * fCS;
		boolean fLocked;
};



#endif

