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

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Аватара пользователя
pda
постоялец
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

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

Сообщение 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, которые работают как системная функция, но выделяют память, которая автоматически освободиться при выходе из функции.

Предлагаю желающим заценить реализацию и сказать что думаете... :)
wadman
постоялец
Сообщения: 122
Зарегистрирован: 18.10.2016 14:54:28
Контактная информация:

Сообщение wadman »

Интересная идея... Линуксы и иже с ними поддерживаются? :)
sts
энтузиаст
Сообщения: 519
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Сообщение sts »

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

Добавлено спустя 20 минут 16 секунд:
емае и когда до этих бестолочей дойдет добавить дефолтные методы в класс.
Аватара пользователя
pda
постоялец
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Сообщение pda »

wadman писал(а):Линуксы и иже с ними поддерживаются?

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

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

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

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

Возможно был баг в компиляторе. У меня уже не осталось 2006, да и устанавливать её сейчас та ещё история. Впрочем, я попробую написать тест побольше, с кучей дополнительных вызовов, чтобы убедиться, что компилятор не удаляет record раньше времени.
wadman
постоялец
Сообщения: 122
Зарегистрирован: 18.10.2016 14:54:28
Контактная информация:

Сообщение wadman »

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

Я-бы и сам проверил, что естественно быстрее, чем ждать ответ на форуме, но линукс не под рукой.
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Имхо польза сомнительна, особенно когда завернута в "модный" record - по сути экономия одной строчки кода
То что создал ручками - будь добр ручками удалить
Аватара пользователя
pda
постоялец
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Сообщение pda »

А если у вас не один временный объект, а 10?
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Я не поленюсь и удалю их руками.
Подобное решение ИМХО подойдет когда можно автоматизировать не только удаление, но и создание объектов. Но в качестве Scoped предпочту более "классические" обжект или класс - в чем профит экономии одной строки на автоматической финализации с record?
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

pda, вообще, можно взять за привычку сразу же после кода создания писать код удаления, а не помнить что когда должно уничтожаться...
sts
энтузиаст
Сообщения: 519
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Сообщение sts »

pda писал(а):Возможно был баг в компиляторе. У меня уже не осталось 2006

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

Добавлено спустя 6 минут 16 секунд:
сама по себе идея стоящая, но делать надо изменением языка. лесенка из 10-ка финалли на редкость убогая вещь.
Аватара пользователя
pda
постоялец
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Сообщение pda »

sts писал(а):не 2006 а 6

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

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

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

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

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

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

Не одной, а трёх и отступ на каждый объект. Это, конечно, если вы code style соблюдаете.
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

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

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

ненадо нам в паскале такого))
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

pda писал(а):Проблема в том, что лесенка финализаторов может оказать больше тела функции.


Значит код под рефакторинг -- он никуда не годен.
Аватара пользователя
pda
постоялец
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Сообщение pda »

Лекс Айрин писал(а):Значит код под рефакторинг -- он никуда не годен.

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

Сообщение olegy123 »

эти фокусы TObjectList умеет делать
Ответить