Garbage Collector для Delphi

Несколько лет назад решил попробовать создать Garbage Collector (далее GC) в Delphi, опираясь на богатую на возможности RTTI. Что нужно для работы GC? Один из подходов — обходить все объекты и определять, какие еще используются программой.

Сначала все объекты помечаются как неиспользуемые. Затем помечаем объекты, которые находятся в стэке и области глобальных переменных, как используемые. Далее определяем на какие объекты указывают используемые объекты и их тоже помечаем как используемые и т.д.

Объекты, до которых не смогли дойти при таком обходе, не используются программой, их можно удалять.

RTTI поможет анализировать объекты, т.к. хранит информацию о типе каждого поля объекта. Т.е. мы может определить на какие еще объекты ссылается каждый объект.

Хм … Но Delphi не хранит информацию о типе расположенной в стеке переменной.
Как и о типе глобальных переменных. Это просто адреса и данные …

Читать далее «Garbage Collector для Delphi»

Автоматическое управление временем жизни объектов в Delphi

Garbage Collector для Delphi? Да! Но с некоторыми ограничениями.

Предисловие

Из-за необходимости создать приложение под Android мне пришлось писать на Java. Обычно я пишу на Delphi, причем довольно старом (зато лицензионном). И одно из отличий в написании кода на этих языках станет предметом этой статьи.

Я создаю объекты в Java, почти не задумываясь, что с ними будет в дальнейшем. В смысле кто еще эти объекты использует, кто и когда их уничтожит, освободив ресурсы.
Т.е. примерно так:

Class1 Ojb1 = new Class1();
Class2 Obj2 = new Class2();
...
работа с объектами
...

Можно полностью сосредоточиться на логике программы, алгоритмах.
В Delphi приходится писать намного больше:

Obj1 := TClass1.Create;
try
  Obj2 := TClass2.Create;
  try
    ...
    работа с объектами
    ...
  finally
    FreeAndNil( Obj2 ); // ну или просто Obj2.Free;
  end;
finally
  FreeAndNil( Obj1 ); // ну или просто Obj1.Free;
end;
Читать далее «Автоматическое управление временем жизни объектов в Delphi»

Local Pool для объектов

Анализируя исходный собственных программ, коих за годы накопилось не мало, я заметил что большое количество объектов живут в пределах вызова функции (процедуры, метода). Но при этом для каждого объекта нужно написать свой блок try finally. Если объектов много, все эти вложенные друг в друга try finally сильно засоряют код.

Пример функции отправки файла по протоколу http:

function SendFile( const URL, FileName: string ): Boolean;
var
  HTTP: THTTP;
  PostParams, Files: TStringList;
  Response: TMemoryStream;
begin
  PostParams := TStringList.Create;
  try
    PostParams[ 'login' ] := LOGIN;
    PostParams[ 'pass' ] := PASS;
    
    Files := TStringList.Create;
    try
      Files.Add( FileName );
    
      Response := TMemoryStream.Create;
      try
        Response.SetSize( DEF_RESP_SIZE );
        
        HTTP := THTTP.Create;
        try
          Result := HTTP.Post( URL, PostParams, Files, Response );
        finally
          HTTP.Free;
        end;
      finally
        Response.Free;
      end;
    finally
      Files.Free;
    end;
  finally
    PostParams.Free;
  end;
end;

«Лишние» строки выделены. Половина тела функции получилась «лишней».

Вот бы локальные объекты сами удалялись при выходе из функции. Если использовать интерфейсы (потомков IInterface) вместо объектов, то так и будет. Сработает механизм подсчета ссылок. Но не будешь же каждый стандартный класс оборачивать в интерфейс …

Читать далее «Local Pool для объектов»