Страница 1 из 3

Автоматическое удаление временных объектов

СообщениеДобавлено: 06.07.2017 23:43:52
pda
Всем привет. Давно не заходил на форум. Вот, решил выложить на github одно решение, которое давно в голове крутилось.
Иногда в функции требуется создавать временные объекты. Всякие там TList, TStrings, TStream... Ну и удалить их надо в конце. Причём правила хорошего тона требуют, чтобы объекты были удалены даже если исключение случилось. Значит в try/finally надо оборачивать. Всё ничего, пока объектов 1-2. Если 5-6 или 10, то всё уже не так красиво.

Вот и придумалось решение хранить ссылки на них в автоуправляемом компилятором объекте, который будет удалять их, когда объект покидает область видимости и компилятор удаляет его. Примерно так:
Код: Выделить всё
var
  Scoped: TScoped;
  MyList: TList;
begin
  MyList := Scoped[TList.Create] as TList;
  <...>
end;


и всё. На "end;" MyList автоматически удаляется. А. Ну ещё там есть другие методы, вроде GetMem, которые работают как системная функция, но выделяют память, которая автоматически освободиться при выходе из функции.

Предлагаю желающим заценить реализацию и сказать что думаете... :)

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 09:53:57
wadman
Интересная идея... Линуксы и иже с ними поддерживаются? :)

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 10:20:55
sts
А оно работает стабильно?
Просто я подобное делал на делфе6 и там была такая проблема, ссылка на интерфейс, иногда, зачищалась оптимизатором раньше конца блока (end;) процедуры, т.е. по примеру раньше чем последнее использование MyList в коде, в итоге приходилось в конце блока вызывать какой нибудь левый метод, типа Scoped.MyRelease, который ничего толком не делает но зато не дает оптимизатору зачистить ссылку.

Добавлено спустя 20 минут 16 секунд:
емае и когда до этих бестолочей дойдет добавить дефолтные методы в класс.

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 17:18:32
pda
wadman писал(а):Линуксы и иже с ними поддерживаются?

Должны. Сегодня вечером проверю. Впрочем, в каталоге tests есть тестовый проект для Lazarus. Никто в общем не запрещает запустить... :roll:

sts писал(а):А оно работает стабильно?

Ну... Тесты раз за разом проходят без запинок. В продакшн пока включить не успел. Причём проходят и в debug профиле и в release. В Lazarus сейчас тоже прогнал все мыслимые варианты ключей оптимизации - норм (правда FPC у меня trunk сборка 3.1.0).

sts писал(а):Просто я подобное делал на делфе6

Возможно был баг в компиляторе. У меня уже не осталось 2006, да и устанавливать её сейчас та ещё история. Впрочем, я попробую написать тест побольше, с кучей дополнительных вызовов, чтобы убедиться, что компилятор не удаляет record раньше времени.

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 17:22:22
wadman
pda писал(а):Никто в общем не запрещает запустить...

Я-бы и сам проверил, что естественно быстрее, чем ждать ответ на форуме, но линукс не под рукой.

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 17:49:36
zub
Имхо польза сомнительна, особенно когда завернута в "модный" record - по сути экономия одной строчки кода
То что создал ручками - будь добр ручками удалить

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 18:14:10
pda
А если у вас не один временный объект, а 10?

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 18:23:30
zub
Я не поленюсь и удалю их руками.
Подобное решение ИМХО подойдет когда можно автоматизировать не только удаление, но и создание объектов. Но в качестве Scoped предпочту более "классические" обжект или класс - в чем профит экономии одной строки на автоматической финализации с record?

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 18:44:24
Лекс Айрин
pda, вообще, можно взять за привычку сразу же после кода создания писать код удаления, а не помнить что когда должно уничтожаться...

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 18:54:30
sts
pda писал(а):Возможно был баг в компиляторе. У меня уже не осталось 2006

не 2006 а 6, не баг, работоспособность вашего кода зависит от оптимизатора, хороший оптимизатор заметит что Scoped дальше не используется и финализирует его, что приведет к ошибкам, сделает он это потому что нет никаких оснований считать что MyList зависит от Scoped. В общем, надо испытать на больших блоках кода, на маленьких нету смысла заранее финализировать.

Добавлено спустя 6 минут 16 секунд:
сама по себе идея стоящая, но делать надо изменением языка. лесенка из 10-ка финалли на редкость убогая вещь.

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 19:31:38
pda
sts писал(а):не 2006 а 6

А как там можно было сделать такое? Там не было advanced record. Разве что на object...

sts писал(а):нет никаких оснований считать что MyList зависит от Scoped

Как это нет, когда он туда передан и там хранится ссылка? Да ещё и сильная в современных терминах. Да ещё и все переменные в Delphi/FPC считаются volatile, потому что это ключевое слово в язык не завезли.

Добавлено спустя 1 минуту 7 секунд:
Лекс Айрин писал(а):вообще, можно взять за привычку сразу же после кода создания писать код удаления, а не помнить что когда должно уничтожаться

Проблема не в том, чтобы сразу написать код удаления. Так и делается. Проблема в том, что лесенка финализаторов может оказать больше тела функции.

Добавлено спустя 1 минуту 7 секунд:
zub писал(а):в чем профит экономии одной строки на автоматической финализации с record?

Не одной, а трёх и отступ на каждый объект. Это, конечно, если вы code style соблюдаете.

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 19:53:14
zub
>>Не одной, а трёх и отступ на каждый объект. Это, конечно, если вы code style соблюдаете.
Я имею ввиду что если за основу брать не record, то всеголишь добавится строка Scoped.Free

pda писал(а):Как это нет, когда он туда передан и там хранится ссылка? Да ещё и сильная в современных терминах. Да ещё и все переменные в Delphi/FPC считаются volatile, потому что это ключевое слово в язык не завезли.

ненадо нам в паскале такого))

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 20:01:26
Лекс Айрин
pda писал(а):Проблема в том, что лесенка финализаторов может оказать больше тела функции.


Значит код под рефакторинг -- он никуда не годен.

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 20:15:13
pda
Лекс Айрин писал(а):Значит код под рефакторинг -- он никуда не годен.

Угу. Хорошо, наверное, жить в мире розовых пони, где всегда всё правильно. :) Ну, скажем... Задача сделать функцию, которая распаковывает gzip и сохраняет результат в файл. Входной TFileStream создай, выходной создай. Gzip поток создай. Сам процесс может в одну строчку уложиться, простое копирование из потока в поток. Ну и обвязка... :roll: Три на создание, три на удаление. Ну и try/finally. Счастливого рефакторинга.

Re: Автоматическое удаление временных объектов

СообщениеДобавлено: 07.07.2017 22:16:19
olegy123
эти фокусы TObjectList умеет делать