Я использую асинхронную диаграмму состояний boost для написания программы. В этой программе я общаюсь с другим устройством, используя асинхронный последовательный порт. У меня есть состояние, которое ожидает подтверждения от устройства через последовательный порт, а затем отправляет событие «подтверждение получено». Это хорошо работает, но я также хотел бы реализовать событие «timeout».
В предыдущих программах я использовал операторы switch case для моих конечных автоматов, где у меня был код, который можно было запускать при каждом запуске цикла. Это означало, что я мог запустить код и проверить, должен ли я изменить состояние из-за истечения времени ожидания. Как это:
while(1){
switch (state){
case 0:{
sendMessage();
state = 1;
sendTime = boost::chrono::steady_clock::now();
}
break;
case 1:{
if (isConfirmationReceived()){
// do something
state = 2;
}
else if (boost::chrono::steady_clock::now() > sendTime + boost::chrono::duration<double>(WAIT_LENGTH)){
//raise a time out error
state = 3;
}
}
break;
// etc etc
}
}
Как бы я реализовать что-то вроде этого, используя boost :: StateChart? Должен ли я думать об этом совершенно по-другому?
Я не знаю, является ли это лучшей практикой, но я решил эту проблему, отправив мой SM EvTick
периодически (1 мс или около того) и обработка события в супер состоянии. Вы также можете добавить ClearTimeout() SetTimeout()
а также DisableTimeout()
функции-члены и доступ к ним, как это:
context< TimeoutSuperState >().SetTimeout(1000);
Вы можете разрешить переходу суперсостояния в состояние ошибки по таймауту или опубликовать EvOnTimeout
к SM, который может быть обработан по-разному в зависимости от состояния.
Других решений пока нет …