Является ли реализация Delphi интерфейса подсчета ссылок на будущее - PullRequest
8 голосов
/ 01 февраля 2012

У меня есть вспомогательный класс, который будет широко использоваться в приложении. Реализация опирается на подсчет ссылок интерфейса, идея примерно такова:

...
var
  lHelper: IMyHelper;
begin
  lHelper := TMyHelper.Create(some params);
  ...some code that doesn't have to access lHelper
end;

Таким образом, реализация зависит от выхода IMyHelper из области действия в конце метода, но не раньше.

Итак, что я спрашиваю, могу ли я быть уверен, что в будущем компилятор Delphi не будет играть умно и не выпустит интерфейс сразу после его создания, если к переменной нет доступа в остальной части метода?

Ответы [ 2 ]

10 голосов
/ 01 февраля 2012

ИМХО, вы можете быть уверены в этом. Шаблон вне области видимости, вероятно, останется глобальным для блока инструкций этого метода. Это было бы серьезным изменением.

См. этот комментарий от Барри Келли (от Embarcadero):

Что касается вашего предыдущего комментария о явных переменных: в гипотетическом (и критическом) случае, когда мы оптимизировали использование интерфейсных переменных, мы, скорее всего, не только нарушили бы описанную функциональность, подобную RAII, но также и подход с использованием явных переменных; значения, присвоенные FooNotifier и BarNotifier, не используются, поэтому «теоретически» они могут быть освобождены быстрее и потенциально даже могут использовать одно и то же хранилище.

Но, конечно, разрушение интерфейса может иметь побочные эффекты, и именно на это и положен эффект в посте. Изменение языка таким образом, чтобы подобные побочные эффекты имели видимые изменения, - это не то, что мы добровольно делаем.

Так что вы можете догадаться, что Embarcadero не будет вносить никаких изменений в обратную совместимость здесь. Преимущество повторного использования памяти интерфейса не будет стоить нарушения совместимости и введения побочных эффектов: сохранение указателя (4 или 8 байт) в настоящее время не стоит, особенно когда стек уже выделен и выровнен (используется модель x64). больше стека, чем x86).

Только если сборщик мусора введен в язык (который я не хочу с моей личной точки зрения), время жизни объектов может измениться. Но в этом случае время жизни может быть больше.

Во всех случаях вы можете создать свой собственный код, чтобы быть уверенным, что он будет выпущен в конце метода:

var
  lHelper: IMyHelper;
begin
  lHelper := TMyHelper.Create(some params);
  try 
    ...some code that doesn't have to access lHelper
  finally
    lHelper := nil; // release the interface count by yourself
  end;
end;

Фактически, это код, уже сгенерированный компилятором. Написание этого будет совершенно излишним, но это гарантирует, что компилятор не изменяет вам.

Говоря об интерфейсах и подсчете ссылок, учтите потенциальную проблему циклических ссылок в Delphi. См. эту замечательную статью (т.е. "Пример 2-15") о необходимости "слабых указателей" для циклических ссылок интерфейсов.

Другие языки (например, Java или C #) используют сборщик мусора для решения этой проблемы. Задача C использует явный механизм «обнуления слабых указателей» для ее решения - см. это обсуждение или этого SO-ответа для потенциальной реализации . Возможно, будущая версия Delphi может рассмотреть возможность использования реализации, аналогичной модели ARC, представленной в Objective C. Но я подозреваю, что будет явный синтаксис для сохранения совместимости с существующим кодом.

4 голосов
/ 01 февраля 2012

В документации сказано следующее (выделено мной):

На платформе Win32 ссылки на интерфейсы обычно управляются путем подсчета ссылок, который зависит от методов _AddRef и _Release, унаследованных от System / IInterface. Используя стандартную реализацию подсчета ссылок, когда на объект ссылаются только через интерфейсы, нет необходимости уничтожать его вручную; объект автоматически уничтожается, когда последняя ссылка на него выходит за рамки .

Область действия локальной переменной - это метод, поэтому текущая спецификация такова, что _Release не будет вызываться до тех пор, пока метод не будет завершен.

Никогда не обещают, что спецификации не будут изменены в будущем, но я думаю, что вероятность изменений, внесенных в эту часть языка, исчезающе мала.

...