在我的服务器代码中,我使用以下模式创建“刚好及时”对象:
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字符串来做类似的事情呢?例如,如果我想在多线程环境中初始化字符串“刚好及时”?还是我要用一个关键的部分?例如:
function TSomeObject.GetSomeString: string;
var
s :string;
begin
if FSomeString='' then
begin
s:='Test';
// InterlockedCompareExchangePointer(Pointer(FSomeString),s,nil);
end;
result:=FSomeString;
end;发布于 2022-03-25 15:05:31
字符串是引用计数,所以仅仅交换指针是不够的,您也必须管理引用计数,例如:
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;另一种选择是:
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头的原因。
https://stackoverflow.com/questions/71618352
复制相似问题