Дизайн МСМ старается сделать фронт-энды и бэк-энды (позже) максимально взаимозаменяемыми. Конечно, ни один бэкэнд никогда не будет реализовывать каждую функцию, определяемую любым возможным интерфейсом и наоборот, но цель состоит в том, чтобы максимально упростить расширение текущего состояния библиотеки.
Для этого MSM делит функциональность между обеими сторонами: front-end является своего рода пользовательским интерфейсом и носит описательный характер, back-end реализует государственный движок машины.
MSM, основанный на таблице переходов, конкретная государственная машина (или заданный интерфейс) должна обеспечивать таблицу переходов. Эта переходная таблица должна состоять из рядов. И каждый ряд должен подсказать, что это за переход, и осуществить призывы к действиям и охранникам. Государственная машина должна также определять свои области (отмеченные начальными состояниями). И это единственные ограничения для фронтендов. То, как описываются строки, является выбором исполнителя.
Каждая строка должна обеспечивать:
A Source typedef с указанием типа исходного состояния.
A Target typedef с указанием типа целевого состояния.
A Evt typedef с указанием типа события, запускающего переход.
A row_type_tag typedef с указанием типа перехода.
Строки, имеющие тип, требующий переходных действий, должны обеспечивать статическую функцию action_call со следующей подписью: шаблон
Функция получает в качестве параметров (back-end) машину состояния, событие, исходное и целевое состояния и контейнер (в текущем back-end, слияние::set) всех состояний, определенных в машине состояния. Например, поскольку back-end имеет front-end в качестве базового класса, action_call просто определяется как (fsm.*action)(evt).
Строки, имеющие тип, требующий охраны, должны обеспечивать статичную функцию guard_call со следующей подписью:
a_irow_tag: внутренний переход (определяется внутри transition_table) с действиями
g_irow_tag: внутренний переход (определяется внутри transition_table) с защитой
irow_tag: внутренний переход (определяется внутри transition_table) с действиями и охраной
_irow_tag: внутренний переход (определяется внутри transition_table) без действия или охраны. Из-за более высокого приоритета для внутренних переходов это эквивалентно «событию игнорирования»
sm_a_i_row_tag: внутренний переход (определяется внутри internal_transition_table) с действиями
sm_g_i_row_tag: внутренний переход (определяется внутри internal_transition_table) с защитным
sm_i_row_tag: внутренний переход (определяется внутри internal_transition_table) с действиями и охраной
sm__i_row_tag: внутренний переход (определяется внутри internal_transition_table) без действия или охраны. Из-за более высокого приоритета для внутренних переходов это эквивалентно «событию игнорирования»
Кроме того, интерфейс должен обеспечивать определение состояний и государственных машин. Определения государственных машин должны быть предоставлены (реализатор может предоставить их или позволить сделать это каждой конкретной государственной машиной). Различные интерфейсы MSM использовали один или другой подход:
Начальное состояние: Этот типдеф может быть одним состоянием или контейнером mpl и обеспечивает начальные состояния, определяющие одну или несколько ортогональных областей.
transition_table Этот типдеф представляет собой последовательность MPL переходных строк.
конфигурация: этот типдеф представляет собой последовательность MPL известных типов, запускающую особое поведение в бэкэнде, например, если конкретная fsm требует очереди сообщений или захвата исключений.
Государства и государственные машины должны давать (возможно, пустое) определение:
flag_list: флаги активны, когда это состояние или государственная машина становятся текущим состоянием fsm.
deferred_events: события автоматически откладываются, когда состояние является текущим состоянием fsm.
internal_transition_table: внутренние переходы этого состояния.
on_entry и on_exit.
Статья Frontend / Backend interface раздела Meta State Machine (MSM) Chapter 6. Internals может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.