加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 为什么编译器坚持我的函数是内联的呢?

发布时间:2020-12-15 09:37:00 所属栏目:大数据 来源:网络整理
导读:我为什么要来 [DCC Error] ProjectCOWArray.dpr(23): E2426 Inline function must not have asm block program ProjectCOWArray;{$APPTYPE CONSOLE}{$R *.res}type PRefCount = ^TRefCount; TRefCount = array[0..1] of integer; TCOWArrayT = record privat
我为什么要来

[DCC Error] ProjectCOWArray.dpr(23): E2426 Inline function must not have asm block

program ProjectCOWArray;

{$APPTYPE CONSOLE}

{$R *.res}

type
  PRefCount = ^TRefCount;
  TRefCount = array[0..1] of integer;


  TCOWArray<T> = record
  private
    fData: TArray<T>;
  private
    procedure IncRefCount;  <<-- not inline  
  end;


{ TCOWArray<T> }

procedure TCOWArray<T>.IncRefCount;
asm
  {$if defined(win32)}
  mov eax,fData;
  lock inc dword ptr [eax - 8];
  {$ifend}
  {$if defined(win64)}
  mov rax,fData;
  lock inc dword ptr[rax -12];
  {$ifend}
end;

begin
end.

Delphi XE2没有AtomicIncrement,那么我该如何解决这个问题呢?
它想保留汇编程序,因为否则我不能使用锁前缀,我不想使用InterlockedIncrement,因为这是一个WinAPI函数,我不想要那种开销.

解决方法

这是因为泛型功能是在内联引擎之上实现的.适用于内联函数的相同限制适用于泛型函数.编译器编写者只是没有采取额外的步骤来使特定于泛型而不是内联函数的错误消息.

我认为调用InterlockedIncrement可能是你最好的选择,对于没有AtomicIncrement内在的Delphi版本.或者,或者,创建自己的AtomicIncrement版本,该版本仅在Delphi版本中定义,不包含它.并且该函数可以用asm编写.嗯,显然必须写在asm当然.

{$IFNDEF AtomicFunctionsAvailable}
function AtomicIncrement(var Target: Integer): Integer;
asm
  ....
end;
{$ENDIF}

或者如@TLama建议的那样,您可以使用System.SyncObjs单元中的TInterlocked来提供原子操作.

尽管如此,我认为没有必要以这种方式干涉内部.每次写入数组时,通过调用SetLength(…)来实现写数组的副本.例如,这是一个关于写数组实现的非常简单的副本:

unit COWArray;

interface

type
  TCOWArray<T> = record
  private
    FItems: TArray<T>;
    function GetLength: Integer;
    procedure SetLength(Value: Integer);
    function GetItem(Index: Integer): T;
    procedure SetItem(Index: Integer; const Value: T);
  public
    class function New(const Values: array of T): TCOWArray<T>; static;
    property Length: Integer read GetLength write SetLength;
    property Items[Index: Integer]: T read GetItem write SetItem; default;
  end;

implementation

function TCOWArray<T>.GetLength: Integer;
begin
  Result := System.Length(FItems);
end;

procedure TCOWArray<T>.SetLength(Value: Integer);
begin
  System.SetLength(FItems,Value); // SetLength enforces uniqueness
end;

function TCOWArray<T>.GetItem(Index: Integer): T;
begin
  Result := FItems[Index];
end;

procedure TCOWArray<T>.SetItem(Index: Integer; const Value: T);
begin
  System.SetLength(FItems,System.Length(FItems)); // SetLength enforces uniqueness
  FItems[Index] := Value;
end;

class function TCOWArray<T>.New(const Values: array of T): TCOWArray<T>;
var
  i: Integer;
begin
  System.SetLength(Result.FItems,System.Length(Values));
  for i := 0 to high(Values) do
    Result.FItems[i] := Values[i];
end;

end.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读