#ifndef BRNEWHEL_H
#define BRNEWHEL_H
//========================================================================================
//
//     File:		BRNewHel.h
//     Release Version:	$ 1.0d1 $
//
//     Creation Date:	1/21/93
//
//     COPYRIGHT 1993 SYMANTEC CORPORATION. ALL RIGHTS RESERVED. UNPUBLISHED -- RIGHTS
//     RESERVED UNDER THE COPYRIGHT LAWS OF THE UNITED STATES. USE OF COPYRIGHT NOTICE IS
//     PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION OR DISCLOSURE.
//
//     THIS SOFTWARE CONTAINS PROPRIETARY AND CONFIDENTIAL INFORMATION OF SYMANTEC
//     CORPORATION. USE, DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR
//     EXPRESS WRITTEN PERMISSION OF SYMANTEC CORPORATION.
//
//     RESTRICTED RIGHTS LEGEND
//     Use, duplication, or disclosure by the Government is subject to restrictions as set
//     forth in subparagraph (c)(l)(ii) of the Rights in Technical Data and Computer
//     Software clause at DFARS 252.227-7013. Symantec Corporation, 10201 Torre Avenue,
//     Cupertino, CA 95014.
//
//========================================================================================

#ifndef   BRPRIDEB_H
#include "BRPriDeb.h"
#endif

#ifndef   BRAUTODE_H
#include "BRAutoDe.h"
#endif

#ifndef   BREXCTAS_H
#include "BRExcTas.h"
#endif

//========================================================================================
//	CLASS __BR_CBedSubHelper
//========================================================================================

class __BR_CBedSubHelper
{
public:
	
	static void InitializeStorageArray(__BR_CBedSubHelper*array, int size);

private:

	friend class __BR_CBedNewHelper;
		// __BR_CBedSubHelper should be a nested class of __BR_CBedNewHelper

	void* operator new(size_t size);
	void  operator delete(void* object);
	
	__BR_CBedSubHelper(_BR_CAutoDestructObject *subObject, 
					   size_t subObjectSize,
					   __BR_CBedSubHelper	*nextSubHelper);
	~__BR_CBedSubHelper();
	
	static void SetSubHelperFreeListHead(__BR_CBedSubHelper* freeListHead);
	static __BR_CBedSubHelper*  GetSubHelperFreeListHead();
	static void SetSubHelperStorageArray(__BR_CBedSubHelper* freeListHead);
	static __BR_CBedSubHelper*  GetSubHelperStorageArray();

	_BR_CAutoDestructObject *fSubObject;
		// The subobject being constructed.
	
	size_t fSubObjectSize;
		// The size of the subobject being watched.
		// This information is necessary for tracking nested subobjects.
		
	void *fSubObjectVTable;
		// The objects vtable at time of last completed constructor
		
	__BR_CBedSubHelper	*fSiblings;
		// Next link for subobject peer to this one.
};

//========================================================================================
//	CLASS __BR_CBedNewHelper
//
// 		This helper object watches a dynamically allocated object until it is fully 
//		constructed. If an exception is thrown before the object is fully constructed,
//		this helper will delete the object.
//========================================================================================

class __BR_CBedNewHelper : public _BR_CAutoDestructObject
{

public:

    enum
    {
		kMaxNewHelperStackItems = 100,
			// Maximum items on NewHelper stack.
			// This limits 'nested news', i.e. objects that are newed that have
			//   constructors that new objects that have constructors that new objects...
		kNewHelperStackSize = kMaxNewHelperStackItems*sizeof(__BR_CBedNewHelper*),
			// New helper stack size in bytes.

		kSubHelperArraySize = 100,
			// Maximum number of simultaneously tracked subobjects.
			// Subobjects are only tracked until their parent object's constructor
			//   has fully executed.
		kSubHelperArrayByteSize = kSubHelperArraySize*sizeof(__BR_CBedSubHelper)
			// Subobject helper array size in bytes.
    };
	
	__BR_CBedNewHelper();
	~__BR_CBedNewHelper();
	
	_BR_CAutoDestructObject *WatchObject(_BR_CAutoDestructObject *watchedObject,
									   size_t watchedSize) const;
		// Watch watchedObject, return previous watched object.
		// This method is not really const, 
		// but it reduces unnecessary warnings to declare it so.
	
	_BR_CAutoDestructObject *ForgetObject() const;
		// Stop watching any object.
		// This method is not really const, 
		// but it reduces unnecessary warnings to declare it so.
	
	void DeleteWatchedObject();
		// Delete the watched object, including subojects of partially constructed class.
	
	void UpdateForEndConstructor(_BR_CAutoDestructObject *object, size_t size);
		// This method is called only from the BR_END_CONSTRUCTOR macro.

	void PushNewHelper();
		// Push this helper onto the helper stack.
		
	static void Initialize();
		// Initialize the NewHelper and SubHelper modules
		
	static __BR_CBedNewHelper *PopNewHelper();
		// Pop top item from helper stack and return pointer to it.

	static __BR_CBedNewHelper *TopNewHelper();
		// Return pointer to top item on helper stack, but don't pop.

	static void SetNewHelperStackBottom(__BR_CBedNewHelper** stackBottom);
		// Set the per-task global gNewHelperStackBottom
		
	static __BR_CBedNewHelper** GetNewHelperStackBottom();
		// Get the per-task global gNewHelperStackBottom
		
	static void SetNewHelperStackTop(__BR_CBedNewHelper** stackTop);
		// Set the per-task global gNewHelperStackTop

	static __BR_CBedNewHelper** GetNewHelperStackTop();
		// Get the per-task global gNewHelperStackTop
	
private:

	__BR_CBedSubHelper* InList(_BR_CAutoDestructObject *subObject);
		// Search list for entry tracking subObject.
		// Returns NULL if no entry exists.

	_BR_CAutoDestructObject *fWatchedObject;
		// The object being constructed.
	
	void *fObjectVTable;
		// The objects v table at time of last completed constructor
		
	size_t fWatchedSize;
		// The size of the object being watched.
		// This information is necessary for tracking subobjects.
		
	__BR_CBedSubHelper	*fSubHelperList;
		// First link for SubHelper tracking subojects nested in this object.
		// Each subhelper tracks one subobject of the fWatchedObject.
};

//========================================================================================
// CLASS __BR_CBedNewHelper INLINE Functions (Static Task Globals Versions)
//========================================================================================

#ifdef BR_STATIC_TASK_GLOBALS

inline void __BR_CBedNewHelper::SetNewHelperStackBottom(__BR_CBedNewHelper** stackBottom)
{
	BR_CExceptionTaskGlobals::gExceptionTaskGlobals.
					gBedExceptionGlobals.gNewHelperStackBottom = stackBottom;
}

inline __BR_CBedNewHelper** __BR_CBedNewHelper::GetNewHelperStackBottom()
{
	return BR_CExceptionTaskGlobals::gExceptionTaskGlobals.
					gBedExceptionGlobals.gNewHelperStackBottom;
}

inline void __BR_CBedNewHelper::SetNewHelperStackTop(__BR_CBedNewHelper** stackTop)
{
	BR_CExceptionTaskGlobals::gExceptionTaskGlobals.
					gBedExceptionGlobals.gNewHelperStackTop = stackTop;
}

inline __BR_CBedNewHelper** __BR_CBedNewHelper::GetNewHelperStackTop()
{
	return BR_CExceptionTaskGlobals::gExceptionTaskGlobals.
					gBedExceptionGlobals.gNewHelperStackTop;
}

#endif

//========================================================================================
// CLASS __BR_CBedSubHelper INLINE Functions (Static Task Globals Versions)
//========================================================================================

#ifdef BR_STATIC_TASK_GLOBALS

inline void __BR_CBedSubHelper::SetSubHelperFreeListHead(__BR_CBedSubHelper* freeListHead)
{
	BR_CExceptionTaskGlobals::gExceptionTaskGlobals.
					gBedExceptionGlobals.gSubHelperFreeListHead = freeListHead;
}

inline __BR_CBedSubHelper*  __BR_CBedSubHelper::GetSubHelperFreeListHead()
{
	return BR_CExceptionTaskGlobals::gExceptionTaskGlobals.
					gBedExceptionGlobals.gSubHelperFreeListHead;
}

inline void __BR_CBedSubHelper::SetSubHelperStorageArray(__BR_CBedSubHelper* storage)
{
	BR_CExceptionTaskGlobals::gExceptionTaskGlobals.
					gBedExceptionGlobals.gSubHelperStorageArray = storage;
}

inline __BR_CBedSubHelper*  __BR_CBedSubHelper::GetSubHelperStorageArray()
{
	return BR_CExceptionTaskGlobals::gExceptionTaskGlobals.
					gBedExceptionGlobals.gSubHelperStorageArray;
}

#endif

//========================================================================================
// CLASS __BR_CBedNewHelper INLINE Functions (Dynamic Task Globals Versions)
//========================================================================================

#ifndef BR_STATIC_TASK_GLOBALS

inline void __BR_CBedNewHelper::SetNewHelperStackBottom(__BR_CBedNewHelper** stackBottom)
{
	BR_CExceptionTaskGlobals::GetTaskGlobals()->
					gBedExceptionGlobals.gNewHelperStackBottom = stackBottom;
}

inline __BR_CBedNewHelper** __BR_CBedNewHelper::GetNewHelperStackBottom()
{
	return BR_CExceptionTaskGlobals::GetTaskGlobals()->
					gBedExceptionGlobals.gNewHelperStackBottom;
}

inline void __BR_CBedNewHelper::SetNewHelperStackTop(__BR_CBedNewHelper** stackTop)
{
	BR_CExceptionTaskGlobals::GetTaskGlobals()->
					gBedExceptionGlobals.gNewHelperStackTop = stackTop;
}

inline __BR_CBedNewHelper** __BR_CBedNewHelper::GetNewHelperStackTop()
{
	return BR_CExceptionTaskGlobals::GetTaskGlobals()->
					gBedExceptionGlobals.gNewHelperStackTop;
}

#endif

//========================================================================================
// CLASS __BR_CBedSubHelper INLINE Functions (Dynamic Task Globals Versions)
//========================================================================================

#ifndef BR_STATIC_TASK_GLOBALS

inline void __BR_CBedSubHelper::SetSubHelperFreeListHead(__BR_CBedSubHelper* freeListHead)
{
	BR_CExceptionTaskGlobals::GetTaskGlobals()->
					gBedExceptionGlobals.gSubHelperFreeListHead = freeListHead;
}

inline __BR_CBedSubHelper*  __BR_CBedSubHelper::GetSubHelperFreeListHead()
{
	return BR_CExceptionTaskGlobals::GetTaskGlobals()->
					gBedExceptionGlobals.gSubHelperFreeListHead;
}

inline void __BR_CBedSubHelper::SetSubHelperStorageArray(__BR_CBedSubHelper* storage)
{
	BR_CExceptionTaskGlobals::GetTaskGlobals()->
					gBedExceptionGlobals.gSubHelperStorageArray = storage;
}

inline __BR_CBedSubHelper*  __BR_CBedSubHelper::GetSubHelperStorageArray()
{
	return BR_CExceptionTaskGlobals::GetTaskGlobals()->
					gBedExceptionGlobals.gSubHelperStorageArray;
}

#endif

#endif
