OberonCore https://forum.oberoncore.ru/ |
|
NEW в процедуре. https://forum.oberoncore.ru/viewtopic.php?f=29&t=5881 |
Страница 2 из 2 |
Автор: | prospero78 [ Воскресенье, 04 Сентябрь, 2016 12:18 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Почитал документацию повнимательней по Kernel. Вот этим ребятам большущее спасибо: Цитата: Составитель: Ермаков И.Е. Исправления и дополнения: Ильин А.С. Kernel, хоть и рисковый модуль, подкинутым дятлом можно что-нибудь покалечить, но он платформо-независим. Итак Есть в типе Module отличное поле: refcnt- -- хранит количество ссылок на модуль!!! То, что доктор прописал!!!)) Есть там ссылка на то, что с абстрактными типами может быть бяка, если модуль реализации инсталлирует свою фабрику(sic!!!) в абстрактный тип, и при этом модуль реализации не импортируется никаким модулем. Выгрузка такого модуля реализации будет фатальной. (* кто-нибудь, если сталкивались, приведите пример такой инсталляции... Я с трудом себе представляю, как можно влезть в готовый модуль, и что-то там инсталлировать... Речь идёт о декораторе? *) (* это, видимо, та причина, по которой я задним числом подозревал, что с динамическим созданием объектов надо поаккуратней. Вирт, на сколько помню, тоже тут осторожничает *) |
Автор: | prospero78 [ Воскресенье, 04 Сентябрь, 2016 18:18 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Ну что, коллеги?))) Работа топорная, прошу не пинать ногами. Но работает) Некоторые пояснения: модуль должен вызываться через Dialog.Call, а не прямым обращением, так как тот модуль, который вызвал _напрямую_ модуль выгрузки -- будет ожидать возврата из процедуры в модуле выгрузки, и естественно, не позволит по цепочке выгружать модули. Здесь я не контролирую количество ссылок на модули, так как знаю, как эти модули импортируются. Ну, и стоит упомянуть отдельно -- в соответствии с документацией по Kernel -- если модуля нет в памяти, то он загружается при попытке получить указатель на него. Т.е. немного лишнего времени может быть потрачено, но безопасный результат что что-то будет выгружено -- будет точно))) Код: MODULE ОикЗакрытие;
(* модуль обеспечивает выгрузку всех модулей, как внешняя команда *) IMPORT мЯдро := Kernel, мСерв := Services, мЛог := StdLog; TYPE тМодуль = ARRAY 50 OF CHAR; туДейств = POINTER TO RECORD (мСерв.Action) END; VAR список: POINTER TO ARRAY OF тМодуль; счёт: INTEGER; модуль: мЯдро.Module; действ: туДейств; PROCEDURE Модуль_Выгрузить (VAR мод_: тМодуль); BEGIN IF (мод_ # "") THEN модуль := мЯдро.ThisMod(мод_); мЯдро.UnloadMod(модуль) END; END Модуль_Выгрузить; PROCEDURE (сам: туДейств)Do; VAR i: INTEGER; BEGIN FOR i := 0 TO счёт DO Модуль_Выгрузить(список[i]); END; END Do; PROCEDURE Выгрузить*; VAR итер: INTEGER; BEGIN мСерв.DoLater(действ, мСерв.Ticks() + мСерв.resolution DIV 5); мЛог.String(' [выгрузка модулей]'); мЛог.Ln END Выгрузить; PROCEDURE Модуль_Добавить (IN мод_: ARRAY OF CHAR); VAR i: INTEGER; BEGIN FOR i := 0 TO LEN(мод_) - 1 DO список[счёт][i] := мод_[i] END; INC(счёт) END Модуль_Добавить; BEGIN NEW(действ); NEW(список, 100); Модуль_Добавить("ОикГлавный"); Модуль_Добавить("ОикПланировщик"); Модуль_Добавить("ГипОкно_охрана"); END ОикЗакрытие. |
Автор: | Иван Денисов [ Воскресенье, 04 Сентябрь, 2016 18:45 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Чтобы лишние модули у тебя не загружались, лучше используй ThisLoadedMod как в DevDebug Код: PROCEDURE UnloadMod (name: TextMappers.String; VAR ok: BOOLEAN);
VAR mod: Kernel.Module; str: Dialog.String; BEGIN mod := Kernel.ThisLoadedMod(name); IF mod # NIL THEN IF name # "DevDebug" THEN Dialog.ShowParamStatus("#Dev:Unloading", name, "", ""); Kernel.UnloadMod(mod) END; IF mod.refcnt < 0 THEN Dialog.MapParamString("#Dev:Unloaded", name, "", "", str); StdLog.String(str); StdLog.Ln ELSE Dialog.ShowParamMsg("#Dev:UnloadingFailed", name, "", ""); ok := FALSE END ELSE Dialog.ShowParamMsg("#Dev:NotFound", name, "", ""); ok := FALSE; END END UnloadMod; |
Автор: | Alexander Shiryaev [ Воскресенье, 04 Сентябрь, 2016 19:17 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
prospero78 писал(а): ... Код: ... ...PROCEDURE (сам: туДейств)Do; VAR i: INTEGER; BEGIN FOR i := 0 TO счёт DO Модуль_Выгрузить(список[i]); END; END Do; ... счёт - 1 |
Автор: | prospero78 [ Воскресенье, 04 Сентябрь, 2016 19:33 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Это вряд ли -- счёт (-1). Так как массив индексируется с нуля. Индекс цикла и индекс массива точно совпадают. Все 220 модулей успешно выгружаются. Кроме того, который выгружает сам все остальные. Но, он не имеет импортов -- перекомпиляция и выгрузка происходит легко. С тупо висящими 3762 байтами я готов смириться))) Ваня, подсказка про ThisLoadedMod -- существенная!!)) Благодарю, пользую)) Но лишние модули и так выгрузка не загружает. Всё что выгружает -- всё пользуется, всё в памяти. Но если, например, модуль верхнего уровня необходимо выгрузить ,а его нет -- он сначала загрузит все нижележащие))) А это уже некрасиво в моём варианте)) При запуске -- 1,67 МБ. При загруженной программе дорасчёта -- 5,42 МБ. После отработки выгрузки -- 1,65 МБ. В-общем, тему можно закрывать. (* содержание несколько не соответствует топику, но мой вариант, по моему, на этом форуме -- первое практическое решение))) *) |
Автор: | Valery Solovey [ Понедельник, 05 Сентябрь, 2016 21:46 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
А чем не нравятся DevDebug.Unload и DevDebug.UnloadThis ? |
Автор: | prospero78 [ Вторник, 06 Сентябрь, 2016 09:50 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Тем, что требуется выделение текста в одном случае, и открытый текст исходного кода в фокусе при другой функции. |
Автор: | Иван Денисов [ Вторник, 06 Сентябрь, 2016 11:49 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
prospero78 писал(а): Тем, что требуется выделение текста в одном случае, и открытый текст исходного кода в фокусе при другой функции. Ну вообще то не требуется, UnloadThis выгружает список модулей указанный после себя. Но то, что ты сделал - удобно, если вообще не открыт графический интерфейс, например, - в серверном приложении. Хочешь ты, чтобы сервер подцепил новые модули, посылаешь команду на выгрузку, планируется выгрузка, и потом в подходящий момент запускается вот такой, например, как у тебя механизм. |
Автор: | prospero78 [ Вторник, 06 Сентябрь, 2016 12:24 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
По упомянутой команде получалось через раз. Видимо, я что-то делаю не так. Ты читаешь мои мысли. Я как никогда близок к реализации идеи -- "машина, которая сама себе на ходу меняет колёса". Шину сообщений создать под это дело, либо выделить протокол в существующей шине -- это вообще не проблема. Хоть удалённый сервер, хоть локальный, хоть сервер в том же самом процессе)) Алгоритм: 1. Заморозить состояние объекта. 2. Выгрузить модуль-обработчик (старая версия) 3. Скомпилировать модуль-обработчик (новая версия) 4. Загрузить модуль-обработчик (новая версия) 5. Разморозить объект. |
Автор: | Иван Денисов [ Вторник, 06 Сентябрь, 2016 18:08 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
prospero78 писал(а): Ты читаешь мои мысли. Потому, что я подобной штукой пользуюсь в своем расширении Robust. Там только один ББ запускается с GUI, а остальные это вычислительные сервера. И когда я в GUI подготовил новый вариант модуля, то хочу, чтобы сервера его тоже перезагрузили. Посылаю сервисное сообщение. Но у меня задачи попроще, видимо, поэтому выгружаю модули по одному и в четком порядке по очереди. Код: PROCEDURE (msg: ServiceMsg) Processor;
VAR mod: Kernel.Module; BEGIN CASE msg.command OF 1: LogMsg("Get exit message"); Kernel.Quit(0); | 2: IF (msg.comment$ # 'Init') & (msg.comment$ # 'Kernel') THEN mod := Kernel.ThisLoadedMod(SHORT(msg.comment$)); IF mod # NIL THEN Kernel.UnloadMod(mod); LogMsg("Module: " + msg.comment$ + " unloaded.") ELSE LogMsg("Module: " + msg.comment$ + " is not loaded.") END ELSE LogMsg("server: could not unload essential module.") END ELSE LogMsg("Get unknown command with service message."); END END Processor; |
Страница 2 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |