Теперь немного о jassVM потоках.
Разберем с начала.
Мы уже знаем, что при запуске карты, создаётся один jassVM поток-триггер инициализации, который запускает функцию main.
Мы уже знаем, что при запуске карты, создаётся один jassVM поток-триггер инициализации, который запускает функцию main.
Операции выполняются шаг за шагом, функция за функцией, пока он не дойдет до конца функции main и тогда он завершит свое выполнение. Каждая операция выполняется строго после предыдущей.
Стоит заметить, что поток в jassVM - немного не то же самое, что поток в приложении операционной системы - отличие в том, что даже несколько потоков jass не могут выполнить что-то в один и тот же момент времени физически, поэтому их не надо синхронизировать.
Если мы напишем в одной из функций TriggerSleepAction(1), то сценарий зависнет на 1 секунду, после чего продолжит свое выполнение. Это и есть поток, т.е. последовательная обработка заданной цепочки команд.
unryze:
Стек функции живет отдельно, и каждый слип - банально убирает вызов этого стека и даёт другим вещам выполниться
Однако, когда срабатывает событие, например, "Юнит атакован", поток переключается на новую ветку действий.
Эта ветка начинается с функции-условия, заданной в триггере. После неё выполняется функция-действие. Но ничто не мешает вам и в самом действии задавать if-then-else.
С физической точки зрения, между функцией-условием (condition) и функцией-действием (action) есть 3 отличия:
- Условия обрываются, если в них выполнить TriggerSleepAction;
- Условия должны возвращать значения boolean, действия ничего не возвращают;
- Действия не выполняются, если условие того же триггера вернуло false.
- Как только в этот момент оттикает время TriggerSleepAction, ветка действий переключается обратно в функцию, которая вызвала слип (с погрешностью 0.1 сек, а иногда и больше)
Лучше можно рассмотреть на рисунке - сверху вниз показано, какие события отрабатывают в какой момент времени.
Красным справа показано, что таймер переключается на новые и новые ветки действий, несмотря на то, что процессор не успел отработать предыдущие. Вместе с утечками памяти - это и есть та причина, почему карта начинает тормозить и зависать.
Исходя из выше написанного, каждая отработка события триггера переключает поток на другую ветку действий, пока она не завершится или не отработает TriggerSleepAction в одной из других веток.
Функции ExecuteFunc, Preload и .ai скрипты стартуют свои потоки и их выполнение происходит в отдельном стеке. В случае с preload и .ai даже в отдельном глобальном контексте.
После выхода из карты, все потоки завершаются.
Спасибо unryze