Страница 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, благо это можно сделать и красиво и полностью компилеронезависимо