События идентифицируются именами, и хранятся в канале событий (EventChannel).
EventPublisher и EventSubscriber позволяют опубликовать/подписаться на событие в канале.
"Опубликовать" означает то, что при вызове точки doPublish будут вызваны все точки onPublish подписчиков на событие этого имени в одном канале. Возврат управления происходит когда все подписчики завершат работу.
Подписчикам передаются все данные из потока, опубликовавшего событие.
Детали реализации
Дабы не делать линейный поиск события по имени каждый раз как мы его публикуем, компоненты EventPublisher/EventSubscriber заранее находят массив подписчиков в списке, при их создании или вызове метода doSetName. EventPublisherEx - исключение, так как он и был создан с целью публикации по "любому" имени.
Реализована защита от рекурсии - в списке событий хранится не только массив подписчиков, но и флаг того, запущено-ли это событие уже. При попытке вызова появится MessageBox и публикация будет проигнорирована.
Не рекомендуется устанавливать имя события компонента EventSubscriber из его точки onPublish, так как это предотвращает удаление старого события из списка, если на него больше нет подписчиков и издателей (следствие того, что это событие уже будет запущено, и если оно было запущено из EventPublisherEx, и так как он он не увиличивает счётчик ссылок ноды - это бы привело к доступу к освобождённой памяти, что нехорошо)
Само собой всё это дело непотокобезопасно - больше одного потока не могут публиковать события в один и тот-же канал событий. Однако на каждый поток может быть свой канал событий - это должно работать без проблем, так как иного общего стейта нет.
Поддерживаются оба компилятора, Hiasm 4.05 build 186.
Ссылка на zip архив с примерами :
https://drive.google.com/file/d/1UTtXN_fUSDWyWvTg0vTckZvYMZPv0L8Z/view?usp=sharing
Точка doEventName позволяет установить имя события динамически, в обоих компонентах EventPublisher и EventSubscriber
Пустое имя события обрабатывается по особенному - подписка и отписка на событие с таким именем, а так-же публикация такового ничего не делает. Поэтому, это хороший способ отписаться от события (вызвав точку doEventName с пустой строкой).
Примеры, где эти компоненты могут быть полезны
- Вызов логики в динамических контейнерах. (Во всех разом, без необходимости делать цикл с ##select)
- Динамичность. Никто не запрещает менять имена событий в рантайме, добавлять к ним числовые префиксы/постфиксы. Можно свой интерпретатор сделать чёрт возьми, без кучи case/ifelse!
- Глобальный лог ошибок. И вообще любой конечный обработчик чего-либо, который используется во многих частях схемы
- Удобство разработки. Не нужно в больших схемах тащить линии через кучу контейнеров в другую кучу контейнеров - вызовите соответствующиее событие.
При неаккуратном ображении это может привести к обратьному результату, поэтому старайтесь именовать события чётко и ясно, минимизировать количество событий в пределах одного контейнера (там вы можете и так провести линию).