在我的服務器代碼中,我使用以下模式來創建“及時”物件:
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;
uj5u.com熱心網友回復:
字串是參考計數的,因此僅交換指標是不夠的,您還必須管理參考計數,例如:
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://www.uj5u.com/houduan/450263.html
