Я ищу какой-то общий
- Оптимизация
- Корректность
- Расширяемость
совет по моей текущей реализации C ++ Hierarchical State Machine.
Пример
variable isMicOn = false
variable areSpeakersOn = false
variable stream = false
state recording
{
//override block for state recording
isMicOn = true //here, only isMicOn is true
//end override block for state recording
}
state playback
{
//override block for state playback
areSpeakersOn = true //here, only areSpeakersOn = true
//end override block for state playback
state alsoStreamToRemoteIp
{
//override block for state alsoStreamToRemoteIp
stream = true //here, both areSpeakersOn = true and stream = true
//end override block for state alsoStreamToRemoteIp
}
}
goToState(recording)
goToState(playback)
goToState(playback.alsoStreamToRemoteIp)
Осуществление
В настоящее время HSM реализован в виде древовидной структуры, в которой каждое состояние может иметь переменное число состояний в качестве дочерних.
Каждое состояние содержит переменное количество блоков «переопределения» (в std :: map), которые переопределяют базовые значения. В корневом состоянии конечный автомат имеет набор переменных (функций, свойств ...), инициализированных некоторыми значениями по умолчанию. Каждый раз, когда мы входим в дочернее состояние, список «переопределений» определяет переменную и значения, которые должны заменить переменные и значения с тем же именем в родительском состоянии. Обновлен оригинал для наглядности.
Ссылочные переменные
Во время выполнения текущие состояния хранятся в стеке.
Каждый раз, когда ссылаются на переменную, выполняется обход стека вниз в поисках максимального переопределения или, в случае отсутствия переопределений, значения по умолчанию.
Переключение состояний
Каждый раз, когда на один кадр состояния переключается, состояние помещается в стек.
Каждый раз, когда состояние переключается, я отслеживаю спуск дерева, который переводит меня из текущего состояния в корневое состояние. Затем я выполняю спуск дерева из целевого состояния в корневое состояние, пока не увижу, что текущая трасса совпадает с предыдущей. Я объявляю перекресток, где встречаются эти 2 следа. Затем, чтобы переключиться в целевое состояние, я спускаюсь из источника, выталкивая кадры состояния из стека, пока не достигну точки пересечения. Затем я поднимаюсь на целевой узел и помещаю кадры состояния в стек.
Так что для примера кода выше
Трассировка выполнения для переключателя состояния
- Состояние источника = запись
Целевое состояние = также StreamToRemoteIp
спуск с источника = запись-> корень (трасса = [корень])
снижение от цели = такжеStreamToRemoteIp-> воспроизведение-> корень (трассировка = [воспроизведение, корень])
Пересекается в корне.
Чтобы переключиться с записи на StreamToRemoteIp,
- Вывести «запись» из стека (и вызвать ее функцию выхода ... здесь не определено).
- Вставьте «воспроизведение» в стек (и вызовите функцию ввода).
- Вставьте также «StreamToRemoteIp »в стек (и вызовите функцию ввода).