Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 GarbageCollector  [new]
Alexey Kuznetsov
Member

Откуда: Krasnoyarsk
Сообщений: 1141
вот придумался такой класс (использование генериков позволяет теперь сделать так)

 ///<summary> Список объектов которые надо будет удалить за один прием.</summary>
 TGarbageCollector = class
 private
  items: TList<TObject>;
 public
  constructor Create();
  destructor Destroy; override;

  ///<summary> Добавить элемент в список и вернуть свежедобавленный элемент.</summary>
  function add<T>(item: T): T;
 end;

constructor TGarbageCollector.Create();
begin
 items := TObjectList<TObject>.Create(true);
end;

destructor TGarbageCollector.Destroy;
begin
 items.free();

 inherited Destroy;
end;

function TGarbageCollector.add<T>(item: T): T;
begin
 result := item;
end;

Пример использования (упрощенный):
 gc := TGarbageCollector.Create();
 try
  a := gc.add(TA.Create());
  b := gc.add(TB.Create());
  c := gc.add(TC.Create());
 .....
 finally
  gc.free();
 end; 

Удобно когда куча объектов и вложенные try/finally сильно начинают напрягать.
Какие За / Против ?
7 окт 11, 18:34    [11404583]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Gator
Member

Откуда: Москва
Сообщений: 13910
На вскидку про items.free();
А если в TA.Create(...).Members счетчики ссылок? или
TA.Create(TA.Create(TABrotherInLaw.Create(TADaughter.Create(...)... ?
7 окт 11, 18:47    [11404664]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Alexey Kuznetsov
Member

Откуда: Krasnoyarsk
Сообщений: 1141
Gator,

Я не предлагаю универсальное решение.
надо не помещать такие классы в список, а управлять ими как раньше - вручную.
7 окт 11, 18:55    [11404727]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Gator
Member

Откуда: Москва
Сообщений: 13910
Alexey Kuznetsov
Gator,

Я не предлагаю универсальное решение.
надо не помещать такие классы в список, а управлять ими как раньше - вручную.
Тогда Вы уж сами решите pro et contra :)
7 окт 11, 19:10    [11404799]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Maxim Rusov
Member

Откуда: Москва-Питер
Сообщений: 2388
Не понял, при чем здесь генерики. Что раньше было нельзя сделать без генериков?
7 окт 11, 19:24    [11404844]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
fd00ch
Member

Откуда: Нижний Новгород
Сообщений: 5913
Maxim Rusov, обойтись без туевой хучи кастов. Дженерики, по сути, только для этого и нужны

ТС, у тебя метод Add() не делает основного))
7 окт 11, 20:01    [11404967]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Gator
Member

Откуда: Москва
Сообщений: 13910
Maxim Rusov> Не понял, при чем здесь генерики. Что раньше было нельзя сделать без генериков?
Имхо надо было бы для "каждого типа" огород городить, а теперь <> + обмен RTTI
7 окт 11, 20:26    [11405080]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Esperito
Member

Откуда:
Сообщений: 1441
Alexey Kuznetsov
Удобно когда куча объектов и вложенные try/finally сильно начинают напрягать.
Зачем вложенные?
Alexey Kuznetsov
Какие За / Против ?
Почему не TObjectList?
Кроме того, есть работа идёт с наследниками TComponent можно делать сразу так:
+
Pwner := TComponent.Create(nil);
try
  a := TA.Create(Pwner);
  b := TB.Create(Pwner);
  c := TC.Create(Pwner);
finally
  Pwner.Free;
end;
Для не наследников можно извратиться с помощью какого-нибудь класса типа:
+
type
  TObjectPwner = class(TComponent)
...
  constructor Create(AOwner: TComponent; AObject: TObject);
...
...и никаких тяжёлых дженериков.

С дженериками можно вообще наваять scoped objects и не использовать try-finally:
var
  A: Scoped<TA>;
  B: Scoped<TB>;
  C: Scoped<TC>;
begin
  A := TA.Create;
  B := TB.Create;
  C := TC.Create;
  C.MethodOfTC(A, B); // Работа с типами TA, TB, TC и их методами
end; // уничтожение объектов
7 окт 11, 20:28    [11405089]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Gator
Member

Откуда: Москва
Сообщений: 13910
imho тут ключом будет "надо не помещать такие классы в список, а управлять ими как раньше - вручную. "
(хотя классы суть "друзья/потомки")
AFAIR что-то подобное было лет 6 назад на InterfacedObject Где оно?
7 окт 11, 20:40    [11405133]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
fd00ch
Member

Откуда: Нижний Новгород
Сообщений: 5913
Esperito
Почему не TObjectList?
там TObjectList, из дженериков

Esperito
Кроме того, есть работа идёт с наследниками TComponent
ты часто в коде в пределах одного метода создаешь и затем уничтожаешь кучу _компонентов_?))

Esperito
тяжёлых дженериков
? :о)

Esperito
С дженериками можно вообще наваять scoped objects и не использовать try-finally
не уловил - почему в конце созданные объекты должны разрушиться?
7 окт 11, 20:51    [11405172]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Esperito
Member

Откуда:
Сообщений: 1441
fd00ch
там TObjectList, из дженериков
Я вижу, не нужны там дженерики.
fd00ch
ты часто в коде в пределах одного метода создаешь и затем уничтожаешь кучу _компонентов_?))
Есть большой проект, там часто такое встречается. В своих проектах я так не делаю.
fd00ch
Esperito
тяжёлых дженериков
? :о)
Ты в курсе, что они для каждого модуля, где используются, генерируются по отдельности?
fd00ch
не уловил - почему в конце созданные объекты должны разрушиться?
Потому что scoped objects. Реализация, например, такая.
7 окт 11, 22:55    [11405736]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Gator
Member

Откуда: Москва
Сообщений: 13910
Esperito, ещё бы полностью определить эту самую scope area... :(
Давече вопрос возникал о begin Result := String(...); end;
7 окт 11, 23:04    [11405771]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Esperito
Member

Откуда:
Сообщений: 1441
Gator
Esperito, ещё бы полностью определить эту самую scope area... :(
Давече вопрос возникал о begin Result := String(...); end;
+Пример
program Project1;

{$APPTYPE CONSOLE}

uses
  DEHL.References;

type
  TMy = class
  private
    FName: string;
  public
    constructor Create(const AName: string);
    destructor Destroy; override;
  end;

constructor TMy.Create(const AName: string);
begin
  FName := AName;
end;

destructor TMy.Destroy;
begin
  Writeln(FName, ' says: Bye!');

  inherited;
end;

function GetMy: Scoped<TMy>; //inline;
var
  L1, L2: Scoped<TMy>;
begin
  L1 := TMy.Create('L1');
  Result := TMy.Create('R');
  L2 := TMy.Create('L2');
end;

procedure Test;
begin
  Writeln('begin');
  GetMy;
  Writeln('end');
end;

begin
  Writeln('Before test.');
  Test;
  Writeln('After test.');

  Readln;
end.
+Без inline
Before test.
begin
L2 says: Bye!
L1 says: Bye!
end
R says: Bye!
After test.
+С inline
Before test.
begin
end
L2 says: Bye!
L1 says: Bye!
R says: Bye!
After test.
8 окт 11, 00:06    [11406010]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
MMM_Corp
Member

Откуда: Тернопіль, Україна
Сообщений: 2098
я лично против GC в любой реализации, даже когда чтото пишу на яве всегда уничтожаю сам

для приведенного вами примера ничего не мешает сделать список/массив и обёртки для уничтожения, до сих пор не понимаю реальное применение дженериков, перечитывал по сто раз, но так и не понимаю куда их можно засунуть, каюсь...
8 окт 11, 05:28    [11406566]     Ответить | Цитировать Сообщить модератору
 Re: GarbageCollector  [new]
Alexey Kuznetsov
Member

Откуда: Krasnoyarsk
Сообщений: 1141
+ Улучшеная версия:

  ///<summary> Класс позволяющий упростить освобождение памяти.</summary>
 TGarbageCollector = class
 public
  const
   DEFAULT_TAG = 'DEFAULT_TAG';
 private
  items: TDictionary<TObject, string>;
 public
  constructor Create();
  destructor Destroy; override;

  ///<summary> Добавить элемент в список и вернуть свежедобавленный элемент.</summary>
  function add<T>(item: T): T; overload;

  ///<summary> Добавить помеченый элемент в список и вернуть свежедобавленный элемент.</summary>
  function add<T>(const tag: string; item: T): T; overload;

  /// <summary> Произвести сборку мусора с указанной меткой. </summary>
  procedure gc(const tag: string);
 end;

constructor TGarbageCollector.Create();
begin
 items := TObjectDictionary<TObject, string>.Create([doOwnsKeys]);
end;

destructor TGarbageCollector.Destroy;
begin
 items.free();

 inherited Destroy;
end;

function TGarbageCollector.add<T>(item: T): T;
begin
 result := add(DEFAULT_TAG, item);
end;

function TGarbageCollector.add<T>(const tag: string; item: T): T;
begin
 items.add(TObject(item), tag);
 result := item;
end;

procedure TGarbageCollector.gc(const tag: string);
var key: TObject;
    item: TPair<TObject, string>;
    gcList: TList<TObject>;
begin
 gcList := TList<TObject>.Create();
 try
  for item in items do
   begin
    if (item.Value = tag) then
     gcList.add(item.Key);
   end;

  for key in gcList do
   items.remove(key);
 finally
  gcList.free();
 end;
end;
8 окт 11, 10:48    [11406700]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить