//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MemMgr.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm3 *Form3;
//---------------------------------------------------------------------------

__fastcall TForm3::TForm3(TComponent* Owner)
	: TForm(Owner)
{
}

// BeginExample: MemMgr
// Routine: System.SetMemoryManager
// Routine: System.GetMemoryManager
// Type: System.TMemoryManagerEx

// BeginCode
/*
This example demonstrates the use of SetMemoryManager and
GetMemoryManager routines. Note that this example is
thread safe.
*/

bool isMyMemMgr;
TMemoryManagerEx oldMemMgr;
volatile long getMemCalls;
volatile long freeMemCalls;
volatile long reallocMemCalls;
volatile long allocMemCalls;

void* __fastcall myGetMem(int size)
{
	//safely increment the counter
	InterlockedIncrement(&getMemCalls);

	//route the call
	return oldMemMgr.GetMem(size);
}

int __fastcall myFreeMem(void* p)
{
	//safely increment the counter
	InterlockedIncrement(&freeMemCalls);

	//route the call
	return oldMemMgr.FreeMem(p);
}

void* __fastcall myReallocMem(void* p, int size)
{
	//safely increment the counter
	InterlockedIncrement(&reallocMemCalls);

	//route the call
	return oldMemMgr.ReallocMem(p, size);
}

void* __fastcall myAllocMem(int size)
{
	//safely increment the counter
	InterlockedIncrement(&allocMemCalls);

	//route the call
	return oldMemMgr.AllocMem(size);
}

void __fastcall TForm3::btUseSysMemMgrClick(TObject *Sender)
{
	//switch button states
	btUseSysMemMgr->Enabled = false;
	btUseMyMemMgr->Enabled = true;

	//set the old memory manager back
	SetMemoryManager(oldMemMgr);

	isMyMemMgr = false;

    //clear out the variables
	getMemCalls     = 0;
	freeMemCalls    = 0;
	reallocMemCalls = 0;
	allocMemCalls   = 0;
}

void __fastcall TForm3::FormDestroy(TObject *Sender)
{
	//set the old memory manager back
	if (isMyMemMgr)
	{
        SetMemoryManager(oldMemMgr);
	}
}

void __fastcall TForm3::Timer1Timer(TObject *Sender)
{
	//Note that IntToStr calls will also Allocate/Free
	//memory so at each timer tick the counts will be +4;

	Form3->edGetMem->Text = IntToStr((int)getMemCalls);
	Form3->edFreeMem->Text = IntToStr((int)freeMemCalls);
	Form3->edReallocMem->Text = IntToStr((int)reallocMemCalls);
	Form3->edAllocMem->Text = IntToStr((int)allocMemCalls);
}

void __fastcall TForm3::btUseMyMemMgrClick(TObject *Sender)
{
	TMemoryManagerEx myMemMgr;

	//switch button states
	btUseSysMemMgr->Enabled = true;
	btUseMyMemMgr->Enabled = false;

	//get the old memory manager
	GetMemoryManager(oldMemMgr);

    //create out instance
	myMemMgr.GetMem = myGetMem;
	myMemMgr.FreeMem = myFreeMem;
	myMemMgr.AllocMem = myAllocMem;
	myMemMgr.ReallocMem = myReallocMem;

    //use defaults for this - not important
	myMemMgr.RegisterExpectedMemoryLeak = oldMemMgr.RegisterExpectedMemoryLeak;
	myMemMgr.UnregisterExpectedMemoryLeak = oldMemMgr.UnregisterExpectedMemoryLeak;

	//clear out the variables
	getMemCalls     = 0;
	freeMemCalls    = 0;
	reallocMemCalls = 0;
	allocMemCalls   = 0;

	//install the new memory manager
	SetMemoryManager(myMemMgr);

	isMyMemMgr = true;
}

void __fastcall TForm3::btDoSomethingClick(TObject *Sender)
{
	void *ptr;
	//perform some new and delete
	for (int i=0; i < 1000; ++i)
	{
		ptr = GetMemory(4);
		FreeMemory(ptr);
	}
}
// EndCode
// EndExample: MemMgr
