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

		IShSMP.h

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

		I3DShSMPUtilities definition

		Author:	Ray Dream
		Date:	3/2/98

		Revision History

		when		who			what & why
		==========	==========	======================================================

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

#ifndef __IShSMP__
#define __IShSMP__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "ComTypes.h"
#include "MCArray.h"
#include "MCSMP.h"
 
//******************************** Globally Unique Ids **********************************

MCDEFINE_GUID_H(IID_IShSMPUtilities);
MCDEFINE_GUID_H(IID_IShCriticalSection);
MCDEFINE_GUID_H(IID_IShLocalStorage);
MCDEFINE_GUID_H(IID_IShSemaphore);
MCDEFINE_GUID_H(IID_IShAtomicCounter);
MCDEFINE_GUID_H(IID_ISMPThread);
MCDEFINE_GUID_H(IID_ISMPRemoteInstructions);
MCDEFINE_GUID_H(IID_IShSMPRemoteLauncher);

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

/// \addtogroup ShellInterface
/// \{



/*****************************************************************************\
*  ISMPThread                                                                 *
*                                                                             *
*    SMP Thread Object                                                        *
*                                                                             *
\*****************************************************************************/
/// SMP Thread object.  
struct ISMPThread : public IMCUnknown
{
	// ****************************************************************************
	//								Work
	// 
	/// Performs the thread's work
	/// 
	virtual MCCOMErr MCCOMAPI Work			() = 0;
};

/*****************************************************************************\
*  IShCriticalSection                                                         *
*                                                                             *
*    SMP Critical Section Object                                              *
*    Used to define a zone in the code accessible by only on SMP thread       *
*    at a time.                                                               *
*                                                                             *
\*****************************************************************************/
/// SMP Critical Section Object. 
/// Used to define a zone in the code accessible by only one SMP thread at a time.
/// Very important!  You <B>do not</B> want to have two threads modifying data at the same time.
/// But, it's better to use TMCCriticalSection directly, rather than this interface.
struct IShCriticalSection : public IMCUnknown
{
	virtual void	 MCCOMAPI Enter			() = 0;
	virtual void	 MCCOMAPI Leave			() = 0;
};

/*****************************************************************************\
*  IShLocalStorage                                                            *
*                                                                             *
*    SMP Local Storage Object                                                 *
*    A variable that can have a different value depending on the current      *
*    SMP thread                                                               *
*                                                                             *
\*****************************************************************************/
/// SMP Local Storage Object
///
/// A variable that can have a different value based on the current SMP thread.
/// Use TMCLocalStorage directly instead of this.
struct IShLocalStorage : public IMCUnknown
{
	virtual void*	 MCCOMAPI GetValue		() = 0;
	virtual void	 MCCOMAPI SetValue		(void* value) = 0;
};

/*****************************************************************************\
*  IShSemaphore                                                               *
*                                                                             *
*    SMP Semaphore Object                                                     *
*                                                                             *
\*****************************************************************************/
/// SMP Semaphore Object
struct IShSemaphore: public IMCUnknown
{
	virtual void	 MCCOMAPI Signal		() = 0;
	virtual boolean  MCCOMAPI WaitForSignal	(boolean wait) = 0;
};

/*****************************************************************************\
*  IShAtomicCounter                                                           *
*                                                                             *
*    SMP Atomic Counter Object                                                *
*    Ensures counter are incremented even when used simultaneously            *
*    be different SMP threads                                                 *
*                                                                             *
\*****************************************************************************/
/// SMP Atomic Counter Object - Do not use.  Use the TMCAtomicCounter class instead.
struct IShAtomicCounter: public IMCUnknown
{
	virtual void	 MCCOMAPI SetValue		(int32 value) = 0;
	virtual int32	 MCCOMAPI GetValue		() = 0;
	virtual void	 MCCOMAPI Increment		() = 0;
	virtual void	 MCCOMAPI Decrement		() = 0;
};

/*****************************************************************************\
*  ISMPRemoteInstructions                                                     *
*                                                                             *
*    SMP Remote Instructions Object                                           *
*    Object containing code to be executed remotely by IShSMPRemoteLauncher   *
*                                                                             *
\*****************************************************************************/
/// SMP Remote Instructions Object
/// 
/// Object containing code to be executed remotely by IShSMPRemoteLauncher
///
struct ISMPRemoteInstructions : public IMCUnknown
{
	virtual void*	 MCCOMAPI Execute		() = 0;
};

/*****************************************************************************\
*  IShSMPRemoteLauncher                                                       *
*                                                                             *
*    SMP Remote Launcher Object                                               *
*    Object taking care of launching execution of code defined by             *
*    ISMPRemoteInstructions by one thread into the context of another         *
*                                                                             *
\*****************************************************************************/
/// SMP Remote Launcher Object
///
/// Object taking care of launching execution of code defined by ISMPRemoteInstructions
/// by one thread into the context of another
///
struct IShSMPRemoteLauncher : public IMCUnknown
{
	virtual void	 MCCOMAPI MainLoop		() = 0;
	virtual boolean	 MCCOMAPI Loop			() = 0;
};


class TMainLocalStorageInfos;
class TMCLocalStorageDataPtrArray;
class TMCCriticalSection;

template<class T> class TMCPtrArray;

/// \}

/// \addtogroup Utilities
/// \{

/*****************************************************************************\
*  IShSMPUtilities                                                            *
*                                                                             *
*    SMP Utilities                                                            *
*    This is where it all begins...                                           *
*										                                      *
\*****************************************************************************/
/// SMP Utilities - Utilities for dealing with SMP systems
struct IShSMPUtilities: public IMCUnknown
{
	// -Description: returns the numbers of CPUs on the current platform
	//
	virtual uint32   MCCOMAPI GetNumberOfCPUs				() = 0;
	virtual boolean  MCCOMAPI AreSystemCallsSafe			() = 0;

	// ****************************************************************************
	//								LaunchSMPThread
	// 
	/// Launches a SMP thread
	/// 
	/// \param thread          The thread to launch  
	/// \param stackSize       The memory to allocate for the thread's stack
	/// \param remoteLauncher  the remote launcher to the application (for things that cannot be done in SMP like UI and asserts)  If the remoteLauncher is NULL then the default remote launcher is used.
	/// \param threadPriority  The priority of the thread.
	/// \param abortFlagPtr    Pointer to abort flag (indicates that the thread should abort)
	/// \return The ID of the launched thread
	/// 
	virtual int32    MCCOMAPI LaunchSMPThread	(	ISMPThread*				thread, 
													uint32					stackSize, 
													IShSMPRemoteLauncher*	remoteLauncher, 
													ESmpThreadPriority		threadPriority,
													boolean*				abortFlagPtr
													) = 0;

	virtual void     MCCOMAPI CreateCriticalSection			(IShCriticalSection** criticalSection) = 0;
	virtual void     MCCOMAPI CreateLocalStorage			(IShLocalStorage** localStorage) = 0;
	virtual void     MCCOMAPI CreateLocalStorageWithRelease	(IShLocalStorage** localStorage) = 0;
	virtual void     MCCOMAPI CreateAtomicCounter			(IShAtomicCounter** atomicCounter) = 0;
	virtual void     MCCOMAPI CreateSemaphore				(IShSemaphore** semaphore, int32 maxValue, int32 initialValue) = 0;

	// ****************************************************************************
	//								CreateRemoteLauncher
	// 
	/// Creates an IShSMPRemoteLauncher
	/// 
	/// \param remoteLauncher  Returns a pointer to the launcher created
	/// \param pauseThreadID   If this != 0, it defines the ID of a thread (see IShThreadUtilities.h).  This thread will be automatically paused and resumed as needed
	/// 
	virtual void     MCCOMAPI CreateRemoteLauncher			(IShSMPRemoteLauncher** remoteLauncher, int32 pauseThreadID) = 0;
	virtual void*    MCCOMAPI DoRemoteInstructions			(ISMPRemoteInstructions* remoteInstructions, boolean forceRemote, boolean returnImmediatly) = 0;

	// -Description: returns a pointer to the mainLocalStorage. It is automatically called by the extensions when the initialise
	// the SMP.
	//
	// -Parameters:
	//
	// mainLocalStorage: a reference to a pointer to the main local storage array.
	// holesIndex:		 the array of the free spaces in the localStorage
	//
	virtual void	 MCCOMAPI GetMainLocalStorage			(TMainLocalStorageInfos*&		mainLocalStorage,
															 TMCArray<uint32>*&				holesIndex) = 0;

	// -Description: returns a pointer to the array of local storage. It is automatically called by the extensions when the initialise
	// the SMP.
	//
	// -Parameters:
	//
	// allThreadLocalStorage:		a reference to a pointer to the array of localStorage for each thread
	// allThreadLocalStorageCS:		a reference to the Critical Section for allThreadLocalStorage
	//
	virtual void	 MCCOMAPI GetAllThreadLocalStorage		(TMCPtrArray < TMCLocalStorageDataPtrArray >*&	allThreadLocalStorage,
															 TMCCriticalSection*&							allThreadLocalStorageCS)=0;


	// -Description: returns a pointer to a structure containing the data for SMP that are platform specific
	//
	virtual void*	 MCCOMAPI GetPlatformData() =0;
	
	// This function should not be used in other cases.
	// Return a pointer to an index for a TLS used to know if a thread is in Main process. (Mac Only)
	//
	virtual void*	 MCCOMAPI GetMacTLSIndex() =0;


	
};

/// \}

/// \addtogroup ShellInterface
/// \{

// ****************************************************************************
//							CWhileInExCS	
// 
/// \deprecated Use TMCCriticalSection and CWhileInCS instead.
///
class CWhileInExCS : public TMCObject
{
	public:
		CWhileInExCS(IShCriticalSection *theCS) { fCS=theCS; fCS->Enter(); }
		~CWhileInExCS() {Clean();}
		void Clean() {if (fCS) { fCS->Leave();} fCS = nil;}

	protected:
		IShCriticalSection* fCS;
};
/// \}
#endif