Когда вызывается TInterfacedObject.Destroy (класс ScopedLock) - PullRequest
4 голосов
/ 08 декабря 2010

Мне интересно, когда экземпляр производного класса TInterfacedObject уничтожен и кто вызывает деструктор.Я написал класс ScopedLock, который должен автоматически вызывать метод Release объекта синхронизации, когда экземпляр выходит из области видимости.Это концепция RAII, известная из C ++, но я не знаю, гарантируется ли, что деструктор вызывается, когда экземпляр блокировки выходит из области видимости., но безопасно ли это?

Ответы [ 3 ]

6 голосов
/ 08 декабря 2010

Единственная проблема, если функция встроенная: локальная переменная, содержащая ссылку ILock, будет переведена в область действия функции, вызывающей встроенную функцию. Это может привести к тому, что замок будет жить дольше, чем вы хотели.

С другой стороны, нет необходимости фактически объявлять переменную для хранения ссылки на интерфейс, если вы пишете функцию (например, функцию класса с именем Create), которая возвращает ссылку на интерфейс (в отличие от ссылки на объект). Компилятор создаст скрытый локальный элемент для получения возвращаемого значения (поскольку все управляемые типы, такие как интерфейсы и строки, фактически возвращаются путем передачи переменной результата). Этот скрытый локальный будет действовать точно так же, как явный локальный.

Я написал больше об этом здесь: http://blog.barrkel.com/2010/01/one-liner-raii-in-delphi.html

5 голосов
/ 08 декабря 2010

Да, это сохранить. Ваш код

function Example.Foo: Integer;
var
  lock : ILock;
begin
  lock := ScopedLock<TCriticalSection>.Create(mySync);
  // ...
end;

компилируется как следующий псевдокод

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 выходит из области видимости, его количество ссылок уменьшается, становится равным нулю, и объект блокировки автоматически уничтожается.

0 голосов
/ 08 декабря 2010

Я не вижу, что подход, который вы поддерживаете, хотя и правильный, на самом деле лучше, чем старый добрый Try / Наконец. Вы взяли решение, которое является ясным и явным, и заменили его темным и непрозрачным.

Реальная работа Delphi-код полон Try / Наконец, и поэтому он должен быть естественной идиомой. Я не вижу обратной стороны письма:

mySync.Acquire;
Try
  //do stuff
Finally
  mySync.Release;
End;
...