xtool/contrib/CoreCipher/Source/CoreAtomic.inc

441 lines
9.3 KiB
PHP

// used Critical Simulate Atomic with TMonitor.Enter(obj) and TMonitor.Exit(obj)
// CriticalSimulateAtomic defined so performance to be reduced
// used soft Simulate Critical(ring)
// SoftCritical defined so performance to be reduced
{ * object lock create by qq600585 * }
{ ****************************************************************************** }
{ * https://zpascal.net * }
{ * https://github.com/PassByYou888/zAI * }
{ * https://github.com/PassByYou888/ZServer4D * }
{ * https://github.com/PassByYou888/PascalString * }
{ * https://github.com/PassByYou888/zRasterization * }
{ * https://github.com/PassByYou888/CoreCipher * }
{ * https://github.com/PassByYou888/zSound * }
{ * https://github.com/PassByYou888/zChinese * }
{ * https://github.com/PassByYou888/zExpression * }
{ * https://github.com/PassByYou888/zGameWare * }
{ * https://github.com/PassByYou888/zAnalysis * }
{ * https://github.com/PassByYou888/FFMPEG-Header * }
{ * https://github.com/PassByYou888/zTranslate * }
{ * https://github.com/PassByYou888/InfiniteIoT * }
{ * https://github.com/PassByYou888/FastMD5 * }
{ ****************************************************************************** }
constructor TSoftCritical.Create;
begin
inherited Create;
L := False;
end;
procedure TSoftCritical.Acquire;
{$IFDEF ANTI_DEAD_ATOMIC_LOCK}
var
d: TTimeTick;
{$ENDIF ANTI_DEAD_ATOMIC_LOCK}
begin
{$IFDEF ANTI_DEAD_ATOMIC_LOCK}
d := GetTimeTick;
while L do
if GetTimeTick - d >= 5000 then
RaiseInfo('dead lock');
{$ELSE ANTI_DEAD_ATOMIC_LOCK}
while L do
NOP;
{$ENDIF ANTI_DEAD_ATOMIC_LOCK}
L := True;
end;
procedure TSoftCritical.Release;
begin
L := False;
end;
procedure TSoftCritical.Enter;
begin
Acquire;
end;
procedure TSoftCritical.Leave;
begin
Release;
end;
constructor TCritical.Create;
begin
inherited Create;
LNum := TAtomInt.Create(0);
end;
destructor TCritical.Destroy;
begin
LNum.Free;
inherited Destroy;
end;
procedure TCritical.Acquire;
begin
Inc(LNum.LockP^);
LNum.UnLock;
inherited Acquire;
end;
procedure TCritical.Release;
begin
Dec(LNum.LockP^);
LNum.UnLock;
inherited Release;
end;
procedure TCritical.Enter;
begin
Acquire();
end;
procedure TCritical.Leave;
begin
Release();
end;
function TCritical.IsBusy: Boolean;
begin
Result := LNum.V > 0;
end;
type
PCritical_Struct = ^TCritical_Struct;
TCritical_Struct = record
Obj: TObject;
LEnter: Integer;
LockTick: TTimeTick;
Critical: TCritical;
end;
TGetCriticalLockState = (lsSame, lsNew, lsIdle);
var
CoreLockCritical: TCriticalSection;
CoreComputeCritical: TCriticalSection;
CoreTimeTickCritical: TCriticalSection;
CriticalList: TCoreClassList;
procedure InitCriticalLock;
begin
CoreLockCritical := TCriticalSection.Create;
CoreComputeCritical := TCriticalSection.Create;
CoreTimeTickCritical := TCriticalSection.Create;
CriticalList := TCoreClassList.Create;
end;
procedure FreeCriticalLock;
var
i: Integer;
p: PCritical_Struct;
begin
for i := 0 to CriticalList.Count - 1 do
begin
p := PCritical_Struct(CriticalList[i]);
p^.Critical.Free;
Dispose(p);
end;
CriticalList.Free;
CriticalList := nil;
CoreLockCritical.Free;
CoreLockCritical := nil;
CoreComputeCritical.Free;
CoreComputeCritical := nil;
CoreTimeTickCritical.Free;
CoreTimeTickCritical := nil;
end;
procedure GetCriticalLock(const Obj: TObject; var output: PCritical_Struct; var state: TGetCriticalLockState);
var
i, pIndex: Integer;
p1, p2: PCritical_Struct;
begin
output := nil;
pIndex := -1;
p1 := nil;
i := 0;
while i < CriticalList.Count do
begin
p2 := PCritical_Struct(CriticalList[i]);
if p2^.Obj = Obj then
begin
output := p2;
state := TGetCriticalLockState.lsSame;
exit;
end
else if (p2^.Obj = nil) and (p2^.LEnter = 0) then
begin
p1 := p2;
pIndex := i;
end;
Inc(i);
end;
if p1 <> nil then
begin
p1^.Obj := Obj;
output := p1;
if pIndex > 0 then
CriticalList.Move(pIndex, 0);
state := TGetCriticalLockState.lsIdle;
end
else
begin
new(p1);
p1^.Obj := Obj;
p1^.LEnter := 0;
p1^.LockTick := GetTimeTick();
p1^.Critical := TCritical.Create;
CriticalList.Insert(0, p1);
output := p1;
state := TGetCriticalLockState.lsNew;
end;
end;
procedure _LockCriticalObj(Obj: TObject);
var
p: PCritical_Struct;
ls: TGetCriticalLockState;
begin
CoreLockCritical.Acquire;
GetCriticalLock(Obj, p, ls);
CoreLockCritical.Release;
p^.Critical.Acquire;
p^.LockTick := GetTimeTick();
AtomInc(p^.LEnter);
end;
procedure _UnLockCriticalObj(Obj: TObject);
var
p: PCritical_Struct;
ls: TGetCriticalLockState;
begin
CoreLockCritical.Acquire;
GetCriticalLock(Obj, p, ls);
CoreLockCritical.Release;
AtomDec(p^.LEnter);
if p^.LEnter < 0 then
RaiseInfo('error: unlock failed: illegal unlock');
p^.LockTick := GetTimeTick();
p^.Critical.Release;
end;
procedure _RecycleLocker(const Obj: TObject);
var
p: PCritical_Struct;
i: Integer;
begin
if (CoreLockCritical = nil) or (CriticalList = nil) or (CriticalList.Count = 0) then
exit;
CoreLockCritical.Acquire;
i := 0;
while i < CriticalList.Count do
begin
p := PCritical_Struct(CriticalList[i]);
if p^.Obj = Obj then
begin
CriticalList.Delete(i);
p^.Critical.Free;
Dispose(p);
break;
end
else
Inc(i);
end;
CoreLockCritical.Release;
end;
function DeltaStep(const value_, Delta_: NativeInt): NativeInt;
begin
if Delta_ > 0 then
Result := (value_ + (Delta_ - 1)) and (not(Delta_ - 1))
else
Result := value_;
end;
procedure AtomInc(var x: Int64);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Inc(x);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicIncrement(x);
{$ENDIF FPC}
end;
procedure AtomInc(var x: Int64; const V: Int64);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Inc(x, V);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicIncrement(x, V);
{$ENDIF FPC}
end;
procedure AtomDec(var x: Int64);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Dec(x);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicDecrement(x);
{$ENDIF FPC}
end;
procedure AtomDec(var x: Int64; const V: Int64);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Dec(x, V);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicDecrement(x, V);
{$ENDIF FPC}
end;
procedure AtomInc(var x: UInt64);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Inc(x);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicIncrement(x);
{$ENDIF FPC}
end;
procedure AtomInc(var x: UInt64; const V: UInt64);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Inc(x, V);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicIncrement(x, V);
{$ENDIF FPC}
end;
procedure AtomDec(var x: UInt64);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Dec(x);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicDecrement(x);
{$ENDIF FPC}
end;
procedure AtomDec(var x: UInt64; const V: UInt64);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Dec(x, V);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicDecrement(x, V);
{$ENDIF FPC}
end;
procedure AtomInc(var x: Integer);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Inc(x);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicIncrement(x);
{$ENDIF FPC}
end;
procedure AtomInc(var x: Integer; const V: Integer);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Inc(x, V);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicIncrement(x, V);
{$ENDIF FPC}
end;
procedure AtomDec(var x: Integer);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Dec(x);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicDecrement(x);
{$ENDIF FPC}
end;
procedure AtomDec(var x: Integer; const V: Integer);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Dec(x, V);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicDecrement(x, V);
{$ENDIF FPC}
end;
procedure AtomInc(var x: Cardinal);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Inc(x);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicIncrement(x);
{$ENDIF FPC}
end;
procedure AtomInc(var x: Cardinal; const V: Cardinal);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Inc(x, V);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicIncrement(x, V);
{$ENDIF FPC}
end;
procedure AtomDec(var x: Cardinal);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Dec(x);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicDecrement(x);
{$ENDIF FPC}
end;
procedure AtomDec(var x: Cardinal; const V: Cardinal);
begin
{$IFDEF FPC}
CoreComputeCritical.Acquire;
Dec(x, V);
CoreComputeCritical.Release;
{$ELSE FPC}
System.AtomicDecrement(x, V);
{$ENDIF FPC}
end;