C# ほど簡単ではありませんが、次のようにするとうまくいくかもしれません。
with Lock(mySharedObj) do
begin
//...do something with mySharedObj
UnLock;
end;
手短に
- 保護したいすべてのインスタンスのリストが保持されます。
- 2 番目のスレッドが を呼び出すと
Lock(mySharedObj)
、内部リストで既存のロックが検索されます。既存のロックが見つからない場合は、新しいロックが作成されます。別のスレッドがまだロックを保持している場合、新しいスレッドはブロックされます。
- これが必要なのは、メソッド呼び出しの最後
Unlock
に ILock インスタンスへの参照のみがスコープ外になるかどうかを確認できないためです。(可能であれば、削除できます)。Lock
Unlock
この設計では、アプリケーションが終了するまで解放されることなく、保護するすべてのオブジェクト インスタンスに対して 1 つの TLock が作成されることに注意してください。
これは考慮に入れることができますが、_AddRef と _Release をいじる必要があります。
unit uLock;
interface
type
ILock = interface
['{55C05EA7-D22E-49CF-A337-9F989006D630}']
procedure UnLock;
end;
function Lock(const ASharedObj: TObject): ILock;
implementation
uses
syncobjs, classes;
type
_ILock = interface
['{BAC7CDD2-0660-4375-B673-ECFA2BA0B888}']
function SharedObj: TObject;
procedure Lock;
end;
TLock = class(TInterfacedObject, ILock, _ILock)
private
FCriticalSection: TCriticalSection;
FSharedObj: TObject;
function SharedObj: TObject;
public
constructor Create(const ASharedObj: TObject);
destructor Destroy; override;
procedure Lock;
procedure UnLock;
end;
var
Locks: IInterfaceList;
InternalLock: TCriticalSection;
function Lock(const ASharedObj: TObject): ILock;
var
I: Integer;
begin
InternalLock.Acquire;
try
//***** Does a lock exists for given Shared object
for I := 0 to Pred(Locks.Count) do
if (Locks[I] as _ILock).SharedObj = ASharedObj then
begin
Result := ILock(Locks[I]);
Break;
end;
//***** Create and add a new lock for the shared object
if not Assigned(Result) then
begin
Result := TLock.Create(ASharedObj);
Locks.Add(Result);
end;
finally
InternalLock.Release;
end;
(Result as _ILock).Lock;
end;
{ TLock }
constructor TLock.Create(const ASharedObj: TObject);
begin
inherited Create;
FSharedObj := ASharedObj;
FCriticalSection := TCriticalSection.Create;
end;
destructor TLock.Destroy;
begin
FCriticalSection.Free;
inherited Destroy;
end;
procedure TLock.Lock;
begin
FCriticalSection.Acquire;
end;
function TLock.SharedObj: TObject;
begin
Result := FSharedObj;
end;
procedure TLock.UnLock;
begin
FCriticalSection.Release;
end;
initialization
Locks := TInterfaceList.Create;
InternalLock := TCriticalSection.Create;
finalization
InternalLock.Free;
Locks := nil
end.