首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >何时调用TInterfacedObject.Destroy ( ScopedLock类)

何时调用TInterfacedObject.Destroy ( ScopedLock类)
EN

Stack Overflow用户
提问于 2010-12-08 23:11:59
回答 3查看 1.5K关注 0票数 5

我想知道什么时候TInterfacedObject派生类的实例被销毁,谁调用析构函数。我编写了一个ScopedLock类,当实例超出作用域时,该类应该自动调用同步对象的Release方法。这是一个来自C++的RAII概念,但我不知道是否保证在锁实例超出作用域时调用析构函数。

代码语言:javascript
复制
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 ?

它在一个简单的测试用例中工作得很好,但是它安全吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-12-08 23:38:01

是的,这就是保存。你的代码

代码语言:javascript
复制
function Example.Foo: Integer;
var
  lock : ILock;
begin
  lock := ScopedLock<TCriticalSection>.Create(mySync);
  // ...
end;

被编译为下面的伪代码

代码语言:javascript
复制
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;

您可以看到,当lock var超出作用域时,它的引用计数会递减,变为零,并且锁对象会自动销毁。

票数 6
EN

Stack Overflow用户

发布于 2010-12-09 01:38:46

唯一的问题是如果函数是内联的:包含ILock引用的局部变量将被提升到调用内联函数的函数的作用域。这可能会导致锁的寿命比您想要的更长。

另一方面,如果您编写了一个返回接口引用(而不是对象引用)的函数(例如,一个名为Create的类函数),则不需要实际声明一个变量来保存接口引用。编译器将创建一个隐藏的本地来接收返回值(因为所有托管类型,如接口和字符串实际上都是通过传递一个结果变量来返回的)。这个隐藏的本地将像显式本地一样工作。

我在这里写了更多内容:http://blog.barrkel.com/2010/01/one-liner-raii-in-delphi.html

票数 6
EN

Stack Overflow用户

发布于 2010-12-09 04:34:47

我看不出你所拥护的方法,虽然正确,但实际上比好的旧尝试/最终更好。您采用了一个清晰而明确的解决方案,并将其替换为一个晦涩而不透明的解决方案。

实际工作中,Delphi代码充满了Try/Finally,因此它应该是一种自然的习惯用法。我看不到写作的缺点:

代码语言:javascript
复制
mySync.Acquire;
Try
  //do stuff
Finally
  mySync.Release;
End;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4389024

复制
相关文章

相似问题

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