Страница 1 из 2
Хак для упорядочивания initialization

Добавлено:
08.04.2018 02:24:35
runewalsh
Давно столкнулся с проблемой задания явного порядка
initialization. Задумавшись снова, кое-что придумал ^^
https://github.com/runewalsh/fpc-unit-prioritizerПример использования:
UnitA.pas- Код: Выделить всё
unit UnitA;
interface
uses
Prioritizer;
implementation
initialization
RegisterUnit('UnitA', +1);
writeln('UnitA(+1) инициализирован');
end.
UnitB.pas- Код: Выделить всё
unit UnitB;
interface
uses
Prioritizer;
implementation
initialization
RegisterUnit('UnitB', 0);
writeln('UnitB(0) инициализирован');
end.
UnitC.pas- Код: Выделить всё
unit UnitC;
interface
uses
Prioritizer;
implementation
initialization
RegisterUnit('UnitC', -1);
writeln('UnitC(-1) инициализирован');
end.
main.pas- Код: Выделить всё
uses
UnitB, UnitC, UnitA;
begin
end.
— вызовет секции
initialization в порядке UnitA → UnitB → UnitC, независимо от чьего бы то ни было порядка подключения или взаимных зависимостей.
Решение опирается на недокументированные структуры и гвоздями прибито к
каким-то платформам и версиям FPC, так что не думаю, что вызовет интерес помимо академического. Но однозначно буду использовать сам, т. к. до этого строил список модулей, которому
руками нужно было дёрнуть SortAndInitialize в начале основной программы, что ну очень неудобно.
Re: Хак для упорядочивания initialization

Добавлено:
08.04.2018 07:34:18
olegy123
а если попробовать так
uses
UnitA, UnitB, UnitC ;очень важно чтобы
UnitA, UnitB, UnitC больше нигде не светились в других модулях, даже в
*.lpr или были обработаны в таком же порядке.
runewalsh писал(а):Решение опирается на недокументированные структуры и гвоздями прибито к каким-то платформам и версиям FPC, так что не думаю, что вызовет интерес помимо академического. Но однозначно буду использовать сам, т. к. до этого строил список модулей, которому руками нужно было дёрнуть SortAndInitialize в начале основной программы, что ну очень неудобно.
я думаю, что модули строятся в порядке их описания. Потому, что необходимы перекрытия.
interface
[публична видна везде, не допустимы перекрестные зависимости]
implementation
[локальна видна везде, допустимы перекрестные зависимости - они не видны друг другу]
initialization/finalization
[глобальна, только выполняется 1 раз]Есть стек FIFO модулей, отсюда инициализация выполняется в зависимости поступления в этот стек FIFO. Тут нет никакой магии.
Добавлено спустя 3 минуты 41 секунду:runewalsh писал(а):SortAndInitialize
не думаю что нужно, проще описать инициализирующую функцию, которая бы вызывалась бы вначале
lpr.
Re: Хак для упорядочивания initialization

Добавлено:
08.04.2018 07:42:03
zub
>>Тут нет никакой магии.
Магия начинается при появлении зацикленых uses. Сталкивался с разным порядком инициализации в delphi и fpc - ничего тогда сделать не получилось((
Предлагаемое решение конечно жесть)) гораздо правильней в таких случаях пересмотреть архитектуру и избавится от зацикливаний
Re: Хак для упорядочивания initialization

Добавлено:
08.04.2018 08:00:32
runewalsh
Инициализирующую функцию можно случайно не вызвать, а порядок, выстроенный компилятором, не очевиден и может сбиться в ходе безобидного рефакторинга или удаления «неиспользуемых» модулей, в том-то и дело.
У проблем, возникающих из-за требований к порядку инициализации модулей, всегда есть более красивые решения. Просто иногда так проще.
Представь, что модуль A предоставляет синглтон-пул неких объектов, который инициализируется при первом обращении, а уничтожается в finalization.
Представь, что модуль B выделяет объект из этого пула и в своём finalization возвращает назад.
Представь, что к моменту возвращения пул оказывается уничтожен. Тогда он посчитает это первым обращением, создастся снова и уже не уничтожится.
Такого плана проблемы могут быть, если твой код не идеален, а он никогда не идеален =3, и иногда проще всего решаются именно выставлением приоритетов «какими они задумывались», а не как получилось в uses.
Re: Хак для упорядочивания initialization

Добавлено:
08.04.2018 08:12:24
Awkward
А может, пойти по пути наименьшего сопротивления, если все модули с инициализацией - "наши" кастомные? сделать один глобальный модуль, где прописать структуру для регистрации процедур инициализации, в секции инициализации каждого модуля прописать "регистрацию" в той структуре, а потом, в основном модуле вызвать свою функцию, которая уже отсортирует эти инициализационные как надо и вызовет их в нужном порядке? Так будет "документировано" по крайней мере.
Re: Хак для упорядочивания initialization

Добавлено:
08.04.2018 08:25:30
runewalsh
Это мой первоначальный вариант с «дёргать руками SortAndInitialize». Я решил плюнуть на чистоту подхода, потому что каждый новый проект стабильно начинаю с того, что забываю её вызвать =( Ну и менее удобно из-за худшей семантичности: функции ещё какие-то объявлять, вместо тех же действий непосредственно в init/final.
Re: Хак для упорядочивания initialization

Добавлено:
08.04.2018 08:26:45
olegy123
Awkward писал(а):А может, пойти по пути наименьшего сопротивления, если все модули с инициализацией - "наши" кастомные? сделать один глобальный модуль
такой файл уже есть - LPR
runewalsh писал(а):Такого плана проблемы могут быть, если твой код не идеален, а он никогда не идеален =3, и иногда проще всего решаются именно выставлением приоритетов «какими они задумывались», а не как получилось в uses.
Публикуйте unit в LPR в нужном порядке.. а не где-то там в блоках.
https://stackoverflow.com/questions/230 ... -in-a-unitrunewalsh писал(а):Инициализирующую функцию можно случайно не вызвать, а порядок, выстроенный компилятором, не очевиден и может сбиться в ходе безобидного рефакторинга или удаления «неиспользуемых» модулей, в том-то и дело.
очевиден, он очевиден и компилятору.. то что вы хотите сделать - выльется в итоге в двух, а при финиализации в трехпроходность компилятора.
Добавлено спустя 7 минут 57 секунд:zub писал(а):Магия начинается при появлении зацикленых uses. Сталкивался с разным порядком инициализации в delphi и fpc - ничего тогда сделать не получилось((
магии нет - есть компилятор, в лексоре при чтении кода формируются списки имен и их смысл, строятся ссылки и их зависимости. Не думаю, что порядок выполняется случайным образом, а не по мере поступления кода..
Re: Хак для упорядочивания initialization

Добавлено:
08.04.2018 08:37:42
runewalsh
>Это мой первоначальный вариант с «дёргать руками SortAndInitialize».Алсо, пример «было» — «стало». Ну няшка же? Няшка. Хоть и сломается когда-нибудь.
Re: Хак для упорядочивания initialization

Добавлено:
09.04.2018 13:57:11
Cheb
Сама идея настолько порочна -- одно из худших мест в паскале -- , что приходится ручками брать и переделывать сторонние модули, вырезая из них этот сраный Initialization. Хотя бы тот же opengl. Потому что иначе это превращается в ктулхообразное болото.
А у меня просто: движок использует длл в линуксе, где Initialization просто не срабатывает. Ну, или, раньше так было - не проверял с версии fpc 1.9.8.
Re: Хак для упорядочивания initialization

Добавлено:
09.04.2018 14:04:31
pupsik
runewalsh я верно понимаю: необходима "инициализация" в каждом модуле?
Re: Хак для упорядочивания initialization

Добавлено:
09.04.2018 14:48:28
runewalsh
Нет, модуль может просто ничего нового не делать, такие инициализируются в первую очередь (т. е. как обычно), а все с приоритетами — во вторую.
Re: Хак для упорядочивания initialization

Добавлено:
09.04.2018 15:06:58
pupsik
Вы не поняли...
- Код: Выделить всё
писать в каждом, при необходимости?
initialization
RegisterUnit('UnitC', -1);
writeln('UnitC(-1) инициализирован');
Добавлено спустя 7 минут 32 секунды:Т.е.: нет возможности глобально решить данный вопрос в приложении?
Re: Хак для упорядочивания initialization

Добавлено:
09.04.2018 15:18:24
runewalsh
Ну да, нужно же как-то сообщить приоритет. Я не придумал другого способа убить двух зайцев. А именно, что делает RegisterUnit:
— сообщает «наверх» информацию о модуле (приоритет), initialization которого сейчас выполняется;
— тут же прерывает инициализацию модуля (бросая специальное исключение) — позже она вызовется ещё раз в нужном порядке и RegisterUnit станет no-op'ом.
Глобальным решением была бы поддержка со стороны компилятора, но такого, к счастью, не будет.
Re: Хак для упорядочивания initialization

Добавлено:
09.04.2018 15:40:13
pupsik
По идее глобально позволит в одном месте делать "каку", не заботясь о склерозе.
По модулям... В чём "няшка" то? Как было, так и осталось. "Тыкать" каждый модуль (требуемый).
п.с
возможно и ошибаюсь.
Re: Хак для упорядочивания initialization

Добавлено:
09.04.2018 19:28:16
zub
runewalsh писал(а):Представь, что модуль A предоставляет синглтон-пул неких объектов, который инициализируется при первом обращении, а уничтожается в finalization.
Представь, что модуль B выделяет объект из этого пула и в своём finalization возвращает назад.
Описаная ситуация вполне решается компилятором, единственное условие необходимое для этого - отсутствмие implementation uses и соответственно циклических ссылок.
Топик - борьба с последствиями (и зло в чистом виде ИМХО

), велосипедики и костылики нужно направлять на уход от implementation uses, благо это можно сделать и красиво и полностью компилеронезависимо