Program VmmTest1;
{-Test program for VMM. This test is much more severe than real world}
{ applications. So don't be afraid by the time it requires to execute}

uses
{$IFDEF HugeAlloc} {You must have Brian Foley's TPALLOC package to try this}
  TpAlloc,
{$ENDIF}
  Vmmngr;

const
  AMax = 200;
  Size1 = 2500;
  Size2 = 5000;
  Size3 = 7500;
  HugeSize = 150000;
  DefEmsToKeep = 32; {512k}
  NewRamSize = 32767;

type
  Block1 = array [1..Size1] of byte;
  Block2 = array [1..Size2] of byte;
  Block3 = array [1..Size3] of byte;
  Block1Ptr = ^Block1;
  Block2Ptr = ^Block2;
  Block3Ptr = ^Block3;

var
  VM : Vmm;
  A1 : array [1..AMax] of Block1Ptr;
  A2 : array [1..AMax] of Block2Ptr;
  A3 : array [1..AMax] of Block3Ptr;
  i  : Byte;

  procedure DoClear;
  begin
    Writeln('Clearing Ram area...');
    if not VM.ClearRamArea then
      Writeln('Some blocks are still locked or an error occured.');
    Writeln('RamMaxAvail : ', VM.RamMaxAvail);
  end;

begin
{$IFDEF HugeAlloc}
  UserGetMem := HugeGetMem;
  UserFreeMem := HugeFreeMem;
  if not VM.InitCustom(HugeSize,
                       DefIncr,
                       DefFreeEntries div 2,
                       DefFreeEntries,
                       DefQueueEntries,
                       DefEmsToKeep,
                       DefDskToKeep,
                       'VMM.SWP') then begin
    Writeln('Failed to open virtual memory manager');
    Halt;
  end
{$ELSE}
  if not VM.Init('VMM.SWP') then begin
    Writeln('Failed to open virtual memory manager');
    Halt;
  end
{$ENDIF}
  else begin
    Writeln('Virtual memory manager initialized');
    Writeln('RamMaxAvail : ', VM.RamMaxAvail);
  end;
  (*
  VM.vmOptionsOff(vmDeleteSwap);  {Try this if you want to browse the swap file}
  VM.vmOptionsOff(vmUseDsk);      {Try this to work on disk only}
  VM.vmOptionsOff(vmUseEms);      {Try this to work in Ems only}
  {Disabling both options is not possible}
  *)
  {Link object to dereference handler}
  VM.LinkToDerefHandler;
  {Allocate AMax blocks of each type}
  Writeln('Allocating memory blocks... (',
          (Size1+Size2+Size3)*AMax,
          ' bytes thru ',
          AMax*3,
          ' pointers)');
  for i := 1 to AMax do begin
    VM.GetMemV(A1[i], SizeOf(Block1));
    if A1[i] <> nil then
      FillChar(VmmDrf(A1[i])^, SizeOf(Block1), i);
    VM.GetMemV(A2[i], SizeOf(Block2));
    if A2[i] <> nil then
      FillChar(VmmDrf(A2[i])^, SizeOf(Block2), i);
    VM.GetMemV(A3[i], SizeOf(Block3));
    if A3[i] <> nil then
      FillChar(VmmDrf(A3[i])^, SizeOf(Block3), i);
  end;
  Writeln('Dereferencing all pointers again...');
  for i := AMax downto 1 do begin
    if A1[i] <> nil then
      FillChar(VmmDrf(A1[i])^, SizeOf(Block1), 255-i);
    if A2[i] <> nil then
      FillChar(VmmDrf(A2[i])^, SizeOf(Block2), 255-i);
    if A3[i] <> nil then
      FillChar(VmmDrf(A3[i])^, SizeOf(Block3), 255-i);
  end;
  DoClear;
  Writeln('Locking a block which is likely not in Ram...');
  if not VM.Lock(A3[AMax], true) then
    Writeln('Could not lock the block in Ram.')
  else begin
    DoClear;
    Writeln('Dereferencing the locked pointer...');
    FillChar(VmmDrf(A3[AMax])^, SizeOf(Block3), 0);
    Writeln('Clearing Ram area again...');
    DoClear;
    if not VM.Lock(A3[AMax], false) then
      Writeln('Could not unlock the block in Ram.');
  end;
  Writeln('Deallocating blocks...');
  for i := 1 to AMax do begin
    if A1[i] <> nil then
      VM.FreeMemV(A1[i]);
    if A2[i] <> nil then
      VM.FreeMemV(A2[i]);
    if A3[i] <> nil then
      VM.FreeMemV(A3[i]);
  end;
  Writeln('Destroying memory manager...');
  VM.Done;
  Writeln('Done.');
end.
