?? myldbmemory.pas
字號:
unit MYLDBMemory;
{$I MYLDBVer.inc}
{DEFINE USEDELPHIMM}
interface
uses SysUtils, Classes, windows,
MYLDBExcept, MYLDBConst;
type
TMYLDBMemorySize = Int64; // 5.06
////////////////////////////////////////////////////////////////////////////////
//
// TMYLDBMemoryManager
//
////////////////////////////////////////////////////////////////////////////////
TMYLDBMemoryManager = class (TObject)
private
FMaxMemorySize: TMYLDBMemorySize; // Max Memory Limit
FTotalMemAllocated: TMYLDBMemorySize; // Total allocated memory
FFreeSystemMemorySize: TMYLDBMemorySize; // Free Memory size in system
FAllocMemCallCount: Int64; // count of allocmem calls
FGetMemCallCount: Int64; // count of getmem calls
FFreeMemCallCount: Int64; // count of freemem calls
FReallocMemCallCount: Int64; // count of reallocmem calls
MMLock: TRTLCriticalSection;
public
// Constructor
constructor Create; overload;
// Constructor
constructor Create(MaxMemorySize: TMYLDBMemorySize); overload;
// Destructor
destructor Destroy; override;
// GetMem analog
function GetMem(BufferSize: TMYLDBMemorySize): Pointer;
// AllocMem analog
function AllocMem(BufferSize: TMYLDBMemorySize): Pointer;
// ReAllocMem analog
procedure ReallocMem(var Buffer; BufferSize: TMYLDBMemorySize; ClearTail: Boolean = False);
// ReAllocMem and clear Tail of Buffer
procedure ReallocMemAndClearTail(var Buffer; BufferSize: TMYLDBMemorySize);
// FreeMem and set pointer to nil
procedure FreeAndNillMem(var Buffer);
// FreeMem
procedure FreeMem(const Buffer: Pointer);
// Return buffer size
function GetMemoryBufferSize(Buffer: Pointer): TMYLDBMemorySize;
// Get min from free system memory size and (FMaxMemorySize - FTotalMemAllocated)
function GetFreeMemorySize: TMYLDBMemorySize;
public
property MaxMemorySize: TMYLDBMemorySize read FMaxMemorySize;
property TotalMemAllocated: TMYLDBMemorySize read FTotalMemAllocated;
// statistics usage
property AllocMemCallCount: Int64 read FAllocMemCallCount;
property GetMemCallCount: Int64 read FGetMemCallCount;
property FreeMemCallCount: Int64 read FFreeMemCallCount;
property ReallocMemCallCount: Int64 read FReallocMemCallCount;
end; // TMYLDBMemoryManager
// Memory Manager variable
var MemoryManager: TMYLDBMemoryManager = nil;
// move memory block
procedure MYLDBMove(const Source; var Dest; count : Integer );
implementation
uses Math;
type
TGetMemType = (gmtGetMem, gmtVirtualAlloc, gmtGlobalAlloc);
// Memory Block Header
PMYLDBMemoryBlockHeader = ^TMYLDBMemoryBlockHeader;
TMYLDBMemoryBlockHeader = packed record
Size: Integer;
GetMemType: TGetMemType;
Signature: Cardinal; // Last 4 byte
end;
// Memory Block Footer
PMYLDBMemoryBlockFooter = ^TMYLDBMemoryBlockFooter;
TMYLDBMemoryBlockFooter = packed record
Signature: Cardinal; // = MYLDBMemoryEndSignature
end;
const MYLDBMemorySignature: Cardinal = $ACCACCAC;
MYLDBMemoryEndSignature: Cardinal = $ACCEACCE;
type
TGetMemFunction = packed record
Size: Integer;
GetMemType: TGetMemType;
end;
const
// If Enable MemChecker then use only GetMem function
{$IFDEF DEBUG_MEMCHECK}
GetMemTypes: array[1..1] of TGetMemFunction =
(
(Size: MaxInt; GetMemType: gmtGetMem)
);
{$ELSE}
GetMemTypes: array[1..4] of TGetMemFunction =
(
(Size: 726; GetMemType: gmtGetMem), // 0 - 1024 ==> GetMem
(Size: 64500; GetMemType: gmtGlobalAlloc), // 1025 - 64500 ==> GlobalAlloc
(Size: 1048576; GetMemType: gmtGetMem), // 64500 - 1 MB ... ==> GetMem
(Size: MaxInt; GetMemType: gmtGlobalAlloc) // 1 MB - ... ==> GlobalAlloc
);
{$ENDIF}
function GetMemFunctionType(MemSize: Integer): TGetMemType;
var i: Integer;
begin
// Set GetMem Function for Maximum Size
Result := GetMemTypes[High(GetMemTypes)].GetMemType;
// Find lower diapason
for i:= High(GetMemTypes) downto Low(GetMemTypes) do
if (MemSize <= GetMemTypes[i].Size) then
begin
Result := GetMemTypes[i].GetMemType;
Break;
end;
end;
////////////////////////////////////////////////////////////////////////////////
//
// TMYLDBMemoryManager
//
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
constructor TMYLDBMemoryManager.Create;
begin
FMaxMemorySize := 0;
InitializeCriticalSection(MMLock);
end;//Create
//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
constructor TMYLDBMemoryManager.Create(MaxMemorySize: TMYLDBMemorySize);
begin
Create;
FMaxMemorySize := MaxMemorySize;
end;//Create
//------------------------------------------------------------------------------
// Destructor
//------------------------------------------------------------------------------
destructor TMYLDBMemoryManager.Destroy;
begin
DeleteCriticalSection(MMLock);
{$IFNDEF DEBUG_MEMCHECK}
{$IFDEF DEBUG_MEMLEAKS}
if FTotalMemAllocated <> 0 then
raise EMYLDBException.Create(30003, ErrorGMemoryLeakFound, [FTotalMemAllocated]);
{$ENDIF}
{$ENDIF}
end;//Destructor
//------------------------------------------------------------------------------
// GetMemoryBufferSize
//------------------------------------------------------------------------------
function TMYLDBMemoryManager.GetMemoryBufferSize(Buffer: Pointer): TMYLDBMemorySize;
var
Block: PMYLDBMemoryBlockHeader;
begin
{$IFDEF USEDELPHIMM}
Result := 0;
Exit;
{$ENDIF}
if Buffer = nil then
Result := 0
else
begin
Block := PMYLDBMemoryBlockHeader(PChar(Buffer) - SizeOf(TMYLDBMemoryBlockHeader));
if (Block.Signature = MYLDBMemorySignature) then
Result := Block.Size
else
raise EMYLDBException.Create(30005, ErrorGInvalidPointer);
end;
end;
//GetMemoryBufferSize
//------------------------------------------------------------------------------
// GetMem
//------------------------------------------------------------------------------
function TMYLDBMemoryManager.GetMem(BufferSize: TMYLDBMemorySize): Pointer;
var
NewSize: TMYLDBMemorySize;
BlockHeader: PMYLDBMemoryBlockHeader;
BlockFooter: PMYLDBMemoryBlockFooter;
GetMemType: TGetMemType;
begin
{$IFDEF USEDELPHIMM}
System.GetMem(Result, BufferSize);
Exit;
{$ENDIF}
// Increment Counter
{$IFDEF MEMDEBUG}
Inc(FGetMemCallCount);
{$ENDIF}
// Allocate 0 bytes ?
if (BufferSize = 0) then
raise EMYLDBException.Create(30286, ErrorGCannotAllocateZeroBytes);
// Mem Limit ?
if ((FMaxMemorySize <> 0) and
(BufferSize + FTotalMemAllocated > FMaxMemorySize)) then
raise EMYLDBException.Create(30004, ErrorGMemoryLimitExceeded, [FMaxMemorySize]);
try
// Calculate New Size of Buffer
NewSize := BufferSize + SizeOf(TMYLDBMemoryBlockHeader) + SizeOf(TMYLDBMemoryBlockFooter);
// GetMem
GetMemType := GetMemFunctionType(NewSize);
case GetMemType of
gmtGetMem:
System.GetMem(BlockHeader, NewSize);
gmtVirtualAlloc:
BlockHeader := VirtualAlloc(nil, NewSize, MEM_COMMIT, PAGE_READWRITE);
gmtGlobalAlloc:
BlockHeader := Pointer(GlobalAlloc(GMEM_FIXED, NewSize))
else
raise EMYLDBException.Create(30340, ErrorGUnknownGetMemType, [Integer(GetMemType)]);
end;
// Fill Block Header
BlockHeader.GetMemType := GetMemType;
BlockHeader.Signature := MYLDBMemorySignature;
BlockHeader.Size := BufferSize;
// Fill Block Footer
BlockFooter := Pointer(PChar(BlockHeader) + SizeOf(TMYLDBMemoryBlockHeader) + BufferSize);
BlockFooter.Signature := MYLDBMemoryEndSignature;
Result := Pointer(Cardinal(BlockHeader) + SizeOf(TMYLDBMemoryBlockHeader));
EnterCriticalSection(MMLock);
Inc(FTotalMemAllocated, BufferSize);
LeaveCriticalSection(MMLock);
except
on e: Exception do
raise EMYLDBException.Create(30015, ErrorGGetMemError, [e.Message]);
end;
end;//GetMem
//------------------------------------------------------------------------------
// AllocMem
//------------------------------------------------------------------------------
function TMYLDBMemoryManager.AllocMem(BufferSize:TMYLDBMemorySize):Pointer;
begin
{$IFDEF USEDELPHIMM}
Result := Sysutils.AllocMem(BufferSize);
Exit;
{$ENDIF}
{$IFDEF MEMDEBUG}
Inc(FAllocMemCallCount);
{$ENDIF}
try
Result := self.GetMem(BufferSize);
FillChar(Result^, BufferSize, 0);
finally
//Dec(FGetMemCallCount);
end;
end;//AllocMem
//------------------------------------------------------------------------------
// FreeMem and set Pointer to nil
//------------------------------------------------------------------------------
procedure TMYLDBMemoryManager.FreeAndNillMem(var Buffer);
var
BlockHeader: PMYLDBMemoryBlockHeader;
BlockFooter: PMYLDBMemoryBlockFooter;
FooterIncorrect: Boolean;
begin
{$IFDEF USEDELPHIMM}
System.FreeMemory(Pointer(Buffer));
Pointer(Buffer) := nil;
Exit;
{$ENDIF}
// Increment Counter
{$IFDEF MEMDEBUG}
Inc(FFreeMemCallCount);
{$ENDIF}
try
// Check Header Signature
BlockHeader := PMYLDBMemoryBlockHeader(PChar(Buffer) - SizeOf(TMYLDBMemoryBlockHeader));
if (BlockHeader.Signature <> MYLDBMemorySignature) then
raise EMYLDBException.Create(30001, ErrorGInvalidPointer);
// Check Footer Signature
BlockFooter := Pointer(PChar(Buffer) + BlockHeader.Size);
FooterIncorrect := (BlockFooter.Signature <> MYLDBMemoryEndSignature);
// Calculate TotalMemAllocated
EnterCriticalSection(MMLock);
Dec(FTotalMemAllocated, BlockHeader.Size);
LeaveCriticalSection(MMLock);
// FreeMem
case BlockHeader.GetMemType of
gmtGetMem:
System.FreeMem(BlockHeader);
gmtVirtualAlloc:
VirtualFree(BlockHeader, 0, MEM_RELEASE);
gmtGlobalAlloc:
GlobalFree(Cardinal(Pointer(BlockHeader)));
end;
// Clear Buffer Pointer
Pointer(Buffer) := nil;
// if Footer Signature incorrect then raise
if (FooterIncorrect) then
raise EMYLDBException.Create(30137, ErrorGMemoryOverrunDetected);
except
on EMYLDBException do raise;
on e: Exception do
raise EMYLDBException.Create(30138, ErrorGFreeMemError, [e.Message]);
end;
end;//FreeAndNillMem
//------------------------------------------------------------------------------
// FreeMem
//------------------------------------------------------------------------------
procedure TMYLDBMemoryManager.FreeMem(const Buffer: Pointer);
var Buffer1: Pointer;
begin
Buffer1 := Buffer;
FreeAndNillMem(Buffer1);
end;// FreeMem
//------------------------------------------------------------------------------
// ReallocMem
//------------------------------------------------------------------------------
procedure TMYLDBMemoryManager.ReallocMem(var Buffer; BufferSize: TMYLDBMemorySize; ClearTail: Boolean);
var
BlockHeader: PMYLDBMemoryBlockHeader;
NewBuffer: Pointer;
begin
{$IFDEF USEDELPHIMM}
System.ReallocMem(Pointer(Buffer), BufferSize);
Exit;
{$ENDIF}
// Increment Counter
{$IFDEF MEMDEBUG}
Inc(FReallocMemCallCount);
{$ENDIF}
try
// Check Header Signature
BlockHeader := PMYLDBMemoryBlockHeader(PChar(Buffer) - SizeOf(TMYLDBMemoryBlockHeader));
if (BlockHeader.Signature <> MYLDBMemorySignature) then
raise EMYLDBException.Create(30002, ErrorGInvalidPointer);
// GetMem
NewBuffer := Self.GetMem(BufferSize);
// Copy OldBuffer to NewBuffer
Move(PChar(Buffer)^, NewBuffer^,
min(BufferSize, BlockHeader.Size));
// Clear Tail
if (ClearTail) then
if (BufferSize > BlockHeader.Size) then
FillChar(PChar(PChar(NewBuffer) + BlockHeader.Size)^, BufferSize-BlockHeader.Size, 0);
// Free old buffer
Self.FreeAndNillMem(PChar(Buffer));
// Set Buffer to NewBuffer
Pointer(Buffer) := NewBuffer;
// Correct call counters
{$IFDEF MEMDEBUG}
Dec(FGetMemCallCount);
Dec(FFreeMemCallCount);
{$ENDIF}
except
on e: Exception do
raise EMYLDBException.Create(30014, ErrorGReallocMemError, [e.Message]);
end;
end;//ReallocMem
//------------------------------------------------------------------------------
// ReAllocMem and clear Tail of Buffer
//------------------------------------------------------------------------------
procedure TMYLDBMemoryManager.ReallocMemAndClearTail(var Buffer; BufferSize: TMYLDBMemorySize);
begin
ReallocMem(Buffer, BufferSize, True);
end;//ReallocMemAndClearTail
//------------------------------------------------------------------------------
// GetFreeMemorySize
//------------------------------------------------------------------------------
function TMYLDBMemoryManager.GetFreeMemorySize: TMYLDBMemorySize;
var
Status: TMemoryStatus;
begin
GlobalMemoryStatus(Status);
FFreeSystemMemorySize := Status.dwAvailPhys;
if (FMaxMemorySize = 0) then
Result := FFreeSystemMemorySize
else
Result := Min(FFreeSystemMemorySize, FMaxMemorySize);
end;//GetFreeMemorySize
//------------------------------------------------------------------------------
// move memory block
//------------------------------------------------------------------------------
procedure MYLDBMove(const Source; var Dest; Count : Integer );
var
S, D: PChar;
I, Offset: Integer;
begin
S := PChar(@Source);
D := PChar(@Dest);
Offset := D - S;
if ((Offset > 0) and (Offset < 4)) then
for i := Count-1 downto 0 do
(D+i)^ := (S+i)^
else
if ((Offset > -4) and (Offset < 0)) then
for i := 0 to Count-1 do
(D+i)^ := (S+i)^
else
Move(Source, Dest, Count);
end;
initialization
MemoryManager := TMYLDBMemoryManager.Create;
finalization
MemoryManager.Free;
MemoryManager := nil;
end.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -