Welcome to U.A.C. [O.S.A.]
login / register 
Status: Guest
Архивы форума | iddqd.ru
Wolf 3D
ПравилаПравила ПоискПоиск
18+
Библиотека подпроцедур и параллелизации стейтов (Dec./ZSc.)
   Список разделов - Проекты и идеи - Библиотека подпроцедур и параллелизации стейтов (Dec./ZSc.)Ответить
АвторСообщение
JSO x
- 2nd Lieutenant -
Next rank: = 2nd Lieutenant = after 106 points
1334

Doom Rate: 2.26

Posts quality: +726
Ссылка на пост №1 Отправлено: 10.01.23 01:11:33
Создание зачётной темы (+40)
Доброго времени суток!

Пару месяцев назад в разговоре мимоходом возник вопрос, возможно ли имитировать полноценный вызов процедур внутри Decorate, вместе с возвратом в произвольную точку входа. Возник -- и забылся, так как на чистом Decorate это всё-таки невозможно. Однако вчера я о нём вспомнил, и, так как сейчас практически у всей страны (или у мира?..) идут выходные, за пару дней написал свою реализацию -- на ZScript, но и для Decorate. И немного увлёкся, добавив невозможную параллельность.

Да, я знаю, что людей, пишущих на Decorate + ACS код под GZDoom, не так много -- однако они есть. Тем более что на ZScript библиотеку тоже вполне можно использовать.


* * *
Возможности
:

- Стандартный стек вызовов/стек возврата;
- Разбиение работы одного актора на множество потоков. На каждом из них независимо от других исполняется код (а также в реал-тайме могут подменяться и спрайты, и фреймы).
- Наследование и некоторый полиморфизм написанных процедур. С натяжкой можно сказать, что они идут с модификатором "virtual" (да, всё верно, в Decorate);
- Приостановка и прерывание работы определённого параллельного потока из-под любого другого.

В комплекте также идут несколько примеров использования. Работоспособность проверялась на GZDoom 2.4.0, GZDoom 3.3.0, QZDoom 2.1pre, LZDoom 3.87c, QZDoom g4.5.0, GZDoom 4.8.2.

Примечание: проект находится в бета-версии. Так как я на Decorate ничего не пишу, а в ZScript встроенным механизмом стейтов пользуюсь довольно редко, обновлять проект и править баги буду только по востребованию -- то есть, скорее всего, только тогда, когда кто-то сообщит о недоработке.


* * *
Download
:

Версия, совместимая со всем, начиная с GZDoom 2.4.0;

Версия, требующая минимум GZDoom 4.3.1. Фактически, не отличается ничем, кроме использования Mixin-конструкций. И в данном случае с ними писать даже правильнее, чем без них...


* * *
API и документация
:

Та же документация есть в файле README.md (правда, на английском), примеры использования внутри Decorate -- в директории "/Examples/".


Подпрограммы/Subroutines:

"SUBP_Call( State st )": сохранение текущего адреса и переход на указанную процедуру;

"SUBP_Return()": выталкивание из стека последнего сохранённого адреса, переход по нему.

Максимальное количество вложенных вызовов -- 255.


Параллелизация/Parallelizing:

"PAR_Thread( State startstate[, int steps[, int params]] )": создание нового параллельного потока, начинающего своё выполнение со стейта "startstate" (кстати, этот самый "startstate" также будет и его идентификатором).

╠ Аргумент "steps" определяет, сколько шагов (внимание: стейтов с ненулевой длительностью) параллельный поток имеет право существовать; после чего уничтожается, если его ещё где-то до этого не прервали. По умолчанию -- "PARSTEPS_Infinite", численно равно -1.

╠ "params" задаёт остальные параметры, в основном -- режим копирования спрайтов. Может быть одной из следующих констант:
╟-╖
║ ├ "PARSPR_All" или "PARSPR_Any". Поток будет копировать на актора все встречающиеся спрайты и фреймы, включая пустой "TNT1A0";
║ ├ "PARSPR_SkipTNT1", "PARSPR_SkipTNT1A0", "PARSPR_IgnoreTNT1" или "PARSPR_IgnoreTNT1A0" (является значением по умолчанию). То же самое, но "TNT1A0" игнорируется;
║ ├ "PARSPR_None", "PARSPR_IgnoreAll" или "PARSPR_SkipAll". Поток исключительно для исполнения функций, отключает работу со спрайтами.
║ ├ Флаг "PAREXEC_NoFunctionsCall" (через логическое ИЛИ, "|"). Блокирует вызовы всех функций (...включая "PAR_Stop()", ага).


"PAR_Stop( [State threadid] )": прерывает указанный поток. Если аргумент опущен, то прерывает тот, который его вызвал.

╠ Когда поток встречает инструкцию управления "Stop", "Goto Null", "Goto LightDone", уничтожается весь актор.

╚ Функция "PAR_Stop()" не может исполниться мгновенно, поэтому в данном случае обычно пишется задержка больше нуля: "TNT1 A 1 PAR_Stop".


"PAR_FrozeFlow( State threadid, bool froze )": приостанавливает или возобновляет работу указанного потока в зависимости от своего второго аргумента.

* * *

Скоростных параллельных вычислений вам!

Рейтинг сообщения: +7, отметил(и): lafoxxx [B0S], theleo_ua, Артём, YURA_111, RastaManGames, Mud, Endoomer
2 7 1
lafoxxx [B0S]
= 1st Lieutenant =
Next rank: - Captain - after 58 points
2032

Doom Rate: 1.38

Posts quality: +937
Ссылка на пост №2 Отправлено: 10.01.23 01:35:31
Звучит как что-то, открывающее принципиально новые возможности, но лично я от моддинга и кодинга далёк, поэтому слабо представляю реальные преимущества. Можно попросить привести пару выдуманных примеров реализации (взгляд в возможное будущее) в_противовес к текущему положению дел и ограничениям?
2 2 4
JSO x
- 2nd Lieutenant -
Next rank: = 2nd Lieutenant = after 106 points
1334

Doom Rate: 2.26

Posts quality: +726
Ссылка на пост №3 Отправлено: 10.01.23 01:53:33
Так вот ведь:
JSO x пишет:
<...> примеры использования внутри Decorate -- в директории "/Examples/.


Внутри "SubprocTorches.dec" используется наследование функций. Там же проверял и аналог конструкции "override Smoke_subproc() { /* ... */ Super.Smoke_subproc(); }":
Скрытый текст:

Actor SubprocRedTorchOverride: SubprocGreenTorch {
    States {
    Spawn:
        TRED ABCD 4 SUBP_Call( "Smoke_subproc" )
        Loop
    Smoke_subproc:
        TNT1 A 0 A_SpawnItemEx( "GrenadeSmokeTrail", FRandom( -radius, radius ), FRandom( -radius, radius ), height + FRandom( 5.0, 30.0 ), 0, 0, FRandom( 0.0, 5.0 ) )
        Goto Super::Smoke_subproc
    }
}



В "SubprocBaron.dec" -- прямолинейное объявление и использование пары процедур. Переписано с последовательности стейтов "See:" актора Abaddon из "Shut up and Bleed". По моему мнению, получилось читабельнее. Ну или как минимум структурнее. Оригинал тоже можно переписать на анонимных функциях, но с учётом того, что те же самые паттерны используются и в других местах актора, выйдет более громоздко. Здесь -- просто пример-копия из исходной модификации:
Скрытый текст:

Spawn:
	TNT1 A 0 A_look
	BRUS A 5 Bright A_wander
	TNT1 A 0 A_look
	BRUS A 5 Bright A_wander
	TNT1 A 0 A_look
	BRUS B 5 Bright A_wander
	TNT1 A 0 A_look
	BRUS B 5 Bright A_wander
	TNT1 A 0  A_SpawnItem("HoofStep",0,0,0,0)
	TNT1 A 0 A_SpawnItemEx("WalkFire",0,0,0,1,0,0,0,128)
	TNT1 A 0 A_Quake(2, 4, 0, 512, "")
	TNT1 A 0 A_look
	BRUS C 5 Bright A_wander
	TNT1 A 0 A_look
	BRUS C 5 Bright A_wander
	TNT1 A 0 A_look
	BRUS D 5 Bright A_wander
	TNT1 A 0 A_look
	BRUS D 5 Bright A_wander
	TNT1 A 0  A_SpawnItem("HoofStep",0,0,0,0)
	TNT1 A 0 A_SpawnItemEx("WalkFire",0,0,0,1,0,0,0,128)
	TNT1 A 0 A_Quake(2, 4, 0, 512, "")
	Loop



"ParallelDoomImp.dec" демонстрирует использование как бы асинхронного исполнения сразу нескольких действий. Вот тут совершенно точно то же самое на чистом Decorate будет писаться... ну, несколько дольше.


А внутри "ParallelTechLamp.dec" все четыре состояния лампы имитируются с помощью двух потоков, сдвинутых друг относительно друга на четверть периода. Ну и плюс "учебные" эффекты -- например, запуск одного и того же потока с разным числом допустимых шагов.

Рейтинг сообщения: +6, отметил(и): lafoxxx [B0S], theleo_ua, YURA_111, RastaManGames, Mud, Endoomer
2 7 1
theleo_ua
= Colonel =
Next rank: - Commissar - after 90 points
4800

Doom Rate: 1.8

Posts quality: +1032
Ссылка на пост №4 Отправлено: 14.01.23 01:15:53
Спасибо за труды и за тему (кто поймет тот поймет)
3 1
JSO x
- 2nd Lieutenant -
Next rank: = 2nd Lieutenant = after 106 points
1334

Doom Rate: 2.26

Posts quality: +726
Ссылка на пост №5 Отправлено: 14.01.23 12:46:02
Полагаю, догадываюсь, что в вопросе "Да зачем вообще нужен ZScript".
theleo_ua пишет:
<...> что надо юзать в 2022 (именно 2022, не 2017) - зскрипт (+ ACS там где зскрипт не сможет в требуемые ACS фичи) или decorate + ACS <...>



lafoxxx [B0S] пишет:
Звучит как что-то, открывающее принципиально новые возможности <...>

Кстати, на это не ответил. Скорее, сильно облегчающее жизнь в некоторых местах: проект -- совершенно точно не панацея, хотя, действительно, может лечь на задачи идеально.

Рейтинг сообщения: +1, отметил(и): theleo_ua
2 7 1
JSO x
- 2nd Lieutenant -
Next rank: = 2nd Lieutenant = after 106 points
1334

Doom Rate: 2.26

Posts quality: +726
Ссылка на пост №6 Отправлено: 28.03.23 23:17:37
Наконец-то, через почти два с половиной месяца, поступило первое сообщение об ошибке -- и то, когда я сам посоветовал попробовать библиотеку. Вероятно, показатель, насколько часто у нас на форуме пользуются чем-то подобным.

Исправлено квазинеопределённое поведение при вызове функций стейтовых переходов ("A_Jump()" и подобные) внутри параллельных нитей; ссылка на сам коммит. YURA_111, спасибо!


JSO x пишет:
<...> проект -- совершенно точно не панацея, хотя, действительно, может лечь на задачи идеально.

Кстати -- выяснилось, что в сложных разработках он действительно может экономить огромное количество строк и нервов. Что не может не радовать!

Рейтинг сообщения: +1, отметил(и): YURA_111
2 7 1
YURA_111
UAC Sergeant Major
Next rank: Chief Petty Officer after 82 points
768

Doom Rate: 1.98

Posts quality: +136
Ссылка на пост №7 Отправлено: 10.04.23 10:27:51
JSO x пишет:
Кстати -- выяснилось, что в сложных разработках он действительно может экономить огромное количество строк и нервов. Что не может не радовать!


Учитывая опыт использования, могу только подтвердить каждое слово!

Добавлено спустя 2 дня 22 часа 49 секунд:

lafoxxx [B0S] пишет:
Звучит как что-то, открывающее принципиально новые возможности


Это так и есть на 100% !

Рейтинг сообщения: +1, отметил(и): JSO x
Страница 1 из 1Перейти наверх
   Список разделов - Проекты и идеи - Библиотека подпроцедур и параллелизации стейтов (Dec./ZSc.)