han*_*aad 4 delphi synchronization locking interface
我想知道什么时候TInterfacedObject派生类的实例被销毁,谁调用析构函数.我写了一个ScopedLock类,当实例超出范围时,它应该自动调用同步对象的Release方法.这是从C++中已知的RAII概念,但是当锁实例超出范围时,我不知道是否保证调用析构函数.
ILock = interface
end;
ScopedLock<T: TSynchroObject> = class(TInterfacedObject, ILock)
strict private
sync_ : T;
public
constructor Create(synchro : T); reintroduce;
destructor Destroy;override;
end;
implementation
{ ScopedLock<T> }
constructor ScopedLock<T>.Create(synchro: T);
begin
inherited Create;;
sync_ := synchro;
sync_.Acquire;
end;
destructor ScopedLock<T>.Destroy;
begin
sync_.Release;
inherited;
end;
{ Example }
function Example.Foo: Integer;
var
lock : ILock;
begin
lock := ScopedLock<TCriticalSection>.Create(mySync);
// ...
end; // mySync released ?
Run Code Online (Sandbox Code Playgroud)
它在一个简单的测试用例中运行良好,但是它安全吗?
唯一的问题是如果函数是内联的:包含ILock引用的局部变量将被提升到调用内联函数的函数的范围.这可能会导致锁定的寿命超过您的预期.
另一方面,如果你编写一个返回接口引用的函数(例如一个名为Create的类函数)(而不是对象引用),则不需要实际声明一个变量来保存接口引用.编译器将创建一个隐藏的本地来接收返回值(因为所有托管类型,如接口和字符串实际上是通过传递结果变量返回的).这个隐藏的本地将像显式本地一样行事.
我在这里写了更多关于它的信息:http://blog.barrkel.com/2010/01/one-liner-raii-in-delphi.html
是的,那就是保存.你的代码
function Example.Foo: Integer;
var
lock : ILock;
begin
lock := ScopedLock<TCriticalSection>.Create(mySync);
// ...
end;
Run Code Online (Sandbox Code Playgroud)
编译为以下伪代码
function Example.Foo: Integer;
var
lock : ILock;
begin
lock := ScopedLock<TCriticalSection>.Create(mySync);
lock._AddRef; // ref count = 1
try
// ..
finally
lock._Release; // ref count = 0, free lock object
end;
Run Code Online (Sandbox Code Playgroud)
您可以看到,当lock var超出范围时,其ref计数减少,变为零并且锁定对象自动销毁.