首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带德尔菲字符串的InterlockedCompareExchangePointer

带德尔菲字符串的InterlockedCompareExchangePointer
EN

Stack Overflow用户
提问于 2022-03-25 14:13:21
回答 1查看 150关注 0票数 0

在我的服务器代码中,我使用以下模式创建“刚好及时”对象:

代码语言:javascript
复制
function TSomeObject.GetChildObjects: TChildObjects;
var
  ChildObjects: TChildObjects;
begin
  if FChildObjects=nil then
    begin
      ChildObjects:=TChildObjects.Create;
// Fill child objects here
      if InterlockedCompareExchangePointer(Pointer(FChildObjects),ChildObjects,nil) <> nil then
        ChildObjects.Free;
    end;
  result:=FChildObjects;
end;

这很好,但是我如何使用Delphi字符串来做类似的事情呢?例如,如果我想在多线程环境中初始化字符串“刚好及时”?还是我要用一个关键的部分?例如:

代码语言:javascript
复制
function TSomeObject.GetSomeString: string;
var
  s :string;
begin
  if FSomeString='' then
    begin
      s:='Test';
//      InterlockedCompareExchangePointer(Pointer(FSomeString),s,nil);
    end;
  result:=FSomeString;
end;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-25 15:05:31

字符串是引用计数,所以仅仅交换指针是不够的,您也必须管理引用计数,例如:

代码语言:javascript
复制
function GetStrRec(const S: string): PStrRec; inline;
begin
  Result := PStrRec(PByte(S) - SizeOf(StrRec));
end;

function InterlockedCompareExchangeString(var VTarget: String; const AValue, Compare: String): String; inline;
var
  P: PStrRec;
begin
  Result := '';
  if AValue <> '' then begin
    P := GetStrRec(AValue);
    if P.refCnt > -1 then AtomicIncrement(P.refCnt);
  end;
  Pointer(Result) := InterlockedCompareExchangePointer(Pointer(VTarget), Pointer(AValue), Pointer(Compare));
  if Pointer(Result) <> Pointer(Compare) then begin
    if Result <> '' then begin
      P := GetStrRec(Result);
      if P.refCnt > -1 then AtomicIncrement(P.refCnt);
    end;
    if AValue <> '' then begin
      P := GetStrRec(AValue);
      if P.refCnt > -1 then AtomicDecrement(P.refCnt);
    end;
  end;
end;

另一种选择是:

代码语言:javascript
复制
function GetStrRec(const S: string): PStrRec; inline;
begin
  Result := PStrRec(PByte(S) - SizeOf(StrRec));
end;

function InterlockedCompareExchangeString(var VTarget: String; const AValue, Compare: String): String; inline;
var
  P: PStrRec;
begin
  Result := '';
  Pointer(Result) := InterlockedCompareExchangePointer(Pointer(VTarget), Pointer(AValue), Pointer(Compare));
  if Pointer(Result) = Pointer(Comparand) then
  begin
    if AValue <> '' then begin
      P := GetStrRec(AValue);
      if P.refCnt > -1 then AtomicIncrement(P.refCnt);
    end;
  end
  else if Result <> '' then begin
    P := GetStrRec(Result);
    if P.refCnt > -1 then AtomicIncrement(P.refCnt);
  end;
end;

不幸的是,RTL不公开函数来操作字符串的引用计数,而只是查询它(StringRefCount()),这就是为什么您必须手动访问和操作字符串的内部StrRec头的原因。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71618352

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档