delphi 非线程安全原子增量

5cnsuln7  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(166)

是否存在类似于AtomicIncrement但不具有线程安全性的标准函数?AtomicIncrement既增加参数又将其作为新值返回。Inc是一个过程,Succ不改变参数值。实际上,我在旧代码中使用AtomicIncrement时,没有好看的处理开放数组的方法。所以现在这个问题几乎没有意义。下面是一个示例:

type
  TA = record
    s: string;
    constructor Create(const sparam: string);
  end;

constructor TA.Create(const sparam: string);
begin
  s := sparam;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  a: TArray<TA>;
  i: integer;
begin
  // ancient approach
  SetLength(a, 100);
  i := -1;
  a[AtomicIncrement(i)] := TA.Create('h');
  a[AtomicIncrement(i)] := TA.Create('e');
  a[AtomicIncrement(i)] := TA.Create('l');
  a[AtomicIncrement(i)] := TA.Create('l');
  a[AtomicIncrement(i)] := TA.Create('o');
  SetLength(a, AtomicIncrement(i));

  // modern approach
  a := [];
  a := a + [TA.Create('h')];
  a := a + [TA.Create('e')];
  a := a + [TA.Create('l')];
  a := a + [TA.Create('l')];
  a := a + [TA.Create('o')];
end;
tv6aics1

tv6aics11#

您可以使用此选项:

{$IF DEFINED(CPUARM) OR DEFINED(LINUX) }
FUNCTION PreInc(VAR I : Int8) : Int8; OVERLOAD;
  BEGIN
    INC(I);
    Result:=I
  END;

FUNCTION PreInc(VAR B : UInt8) : UInt8; OVERLOAD;
  BEGIN
    INC(B);
    Result:=B
  END;

FUNCTION PreInc(VAR I : Int16) : Int16; OVERLOAD;
  BEGIN
    INC(I);
    Result:=I
  END;

FUNCTION PreInc(VAR W : UInt16) : UInt16; OVERLOAD;
  BEGIN
    INC(W);
    Result:=W
  END;

FUNCTION PreInc(VAR I : Int32) : Int32; OVERLOAD;
  BEGIN
    INC(I);
    Result:=I
  END;

FUNCTION PreInc(VAR W : UInt32) : UInt32; OVERLOAD;
  BEGIN
    INC(W);
    Result:=W
  END;

FUNCTION PreInc(VAR I : Int64) : Int64; OVERLOAD;
  BEGIN
    INC(I);
    Result:=I
  END;

FUNCTION PreInc(VAR L : UInt64) : UInt64; OVERLOAD;
  BEGIN
    INC(L);
    Result:=L
  END;
{$ELSEIF DEFINED (CPUX64) }
FUNCTION PreInc(VAR I : Int8) : Int8; OVERLOAD; ASSEMBLER;
  ASM
                .NOFRAME
                INC     BYTE PTR [RCX]
                MOV     AL,[RCX]
  END;

FUNCTION PreInc(VAR B : UInt8) : UInt8; OVERLOAD; ASSEMBLER;
  ASM
                .NOFRAME
                INC     BYTE PTR [RCX]
                MOV     AL,[RCX]
  END;

FUNCTION PreInc(VAR I : Int16) : Int16; OVERLOAD; ASSEMBLER;
  ASM
                .NOFRAME
                INC     WORD PTR [RCX]
                MOV     AX,[RCX]
  END;

FUNCTION PreInc(VAR W : UInt16) : UInt16; OVERLOAD; ASSEMBLER;
  ASM
                .NOFRAME
                INC     WORD PTR [RCX]
                MOV     AX,[RCX]
  END;

FUNCTION PreInc(VAR I : Int32) : Int32; OVERLOAD; ASSEMBLER;
  ASM
                .NOFRAME
                INC     DWORD PTR [RCX]
                MOV     EAX,[RCX]
  END;

FUNCTION PreInc(VAR L : UInt32) : UInt32; OVERLOAD; ASSEMBLER;
  ASM
                .NOFRAME
                INC     DWORD PTR [RCX]
                MOV     EAX,[RCX]
  END;

FUNCTION PreInc(VAR I : Int64) : Int64; OVERLOAD; ASSEMBLER;
  ASM
                .NOFRAME
                INC     QWORD PTR [RCX]
                MOV     RAX,[RCX]
  END;

FUNCTION PreInc(VAR L : UInt64) : UInt64; OVERLOAD; ASSEMBLER;
  ASM
                .NOFRAME
                INC     QWORD PTR [RCX]
                MOV     RAX,[RCX]
  END;
{$ELSE }
FUNCTION PreInc(VAR I : Int8) : Int8; OVERLOAD; ASSEMBLER;
  ASM
                INC     BYTE PTR [EAX]
                MOV     AL,[EAX]
  END;

FUNCTION PreInc(VAR B : UInt8) : UInt8; OVERLOAD; ASSEMBLER;
  ASM
                INC     BYTE PTR [EAX]
                MOV     AL,[EAX]
  END;

FUNCTION PreInc(VAR I : Int16) : Int16; OVERLOAD; ASSEMBLER;
  ASM
                INC     WORD PTR [EAX]
                MOV     AX,[EAX]
  END;

FUNCTION PreInc(VAR W : UInt16) : UInt16; OVERLOAD; ASSEMBLER;
  ASM
                INC     WORD PTR [EAX]
                MOV     AX,[EAX]
  END;

FUNCTION PreInc(VAR I : Int32) : Int32; OVERLOAD; ASSEMBLER;
  ASM
                INC     DWORD PTR [EAX]
                MOV     EAX,[EAX]
  END;

FUNCTION PreInc(VAR W : UInt32) : UInt32; OVERLOAD; ASSEMBLER;
  ASM
                INC     DWORD PTR [EAX]
                MOV     EAX,[EAX]
  END;

FUNCTION PreInc(VAR I : Int64) : Int64; OVERLOAD; ASSEMBLER;
  ASM
                XOR     EDX,EDX
                INC     EDX
                ADD     [EAX],EDX
                DEC     EDX
                ADC     [EAX+4],EDX
                MOV     EDX,[EAX+4]
                MOV     EAX,[EAX]
  END;

FUNCTION PreInc(VAR L : UInt64) : UInt64; OVERLOAD; ASSEMBLER;
  ASM
                XOR     EDX,EDX
                INC     EDX
                ADD     [EAX],EDX
                DEC     EDX
                ADC     [EAX+4],EDX
                MOV     EDX,[EAX+4]
                MOV     EAX,[EAX]
  END;
{$ENDIF }

这在 Delphi 中实现了一个PreInc(C的--X操作符),在英特尔处理器的汇编中进行了优化。实现PostInc(X++)、PreAdd(X+=Y)和PostAdd由用户决定:-)

相关问题