Совместные процедуры в c ++ — это действительно мощный метод для реализации конечных автоматов, однако примеры, которые я нахожу в Интернете, слишком упрощены, например. они обычно представляют собой некий итератор, который после вызова некоторой подпрограммы «Next» движется дальше, зависящий только от начальных аргументов сопрограммы. Однако в достаточно сложных конечных автоматах на основе событий каждый следующий шаг зависит от конкретного полученного события, которое вызвало возобновление работы, а также должны быть реализованы некоторые обработчики событий по умолчанию для событий, которые могут произойти в любое время.
Предположим, у нас есть простой телефонный автомат.
СОСТОЯНИЕ: ВЫКЛЮЧЕНИЕ -> [EVT: набор номера] -> [СОСТОЯНИЕ: НАБОР] -> [EVT: НАБОР НОМЕРА] -> СОСТОЯНИЕ: РАЗГОВОР.
Теперь я хотел бы сопрограмму, которая увидит что-то вроде.
PhoneSM()
{
HookOf();
Yield_Till(DialTone_Event);
Dial();
Yield_Till(EndOfDial_Event);
Talk();
...
}
например требования
Yield_Till будет продолжаться только тогда, когда будет получено определенное событие (как ???), когда возобновится запуск программы. Если нет, то он должен вернуться снова.
Yield_Till должен знать, как запускать события для обработчиков по умолчанию, таких как Hangup_Event, потому что на самом деле это может произойти в любое время, и добавлять его каждый раз будет сложнее.
Будем весьма благодарны за любую помощь в реализации c ++ (только !!!) или готовой инфраструктуры для удовлетворения требований.
Мне кажется, что вы пытаетесь закодировать конечный автомат, управляемый событиями, как последовательную блок-схему. Разница между диаграммами состояний и блок-схемами довольно фундаментальна и объясняется, например, в статье. «Ускоренный курс в UML State Machines»:
Конечный автомат должен быть закодирован как одноразовая функция, которая обрабатывает текущее событие и возвращается без уступок или блокировок. Если вы хотите использовать сопрограммы, вы можете вызвать эту функцию конечного автомата из подпрограммы, которая затем выдается после каждого события.
Большинство сопутствующих библиотек не поддерживают сложную функцию yield. Они просто уступают, и ваша совместная рутина получит контроль в любой произвольной точке. Следовательно, после выхода вы должны будете протестировать соответствующие условия в вашем коде и снова выполнить, если они не выполняются. В этом коде вы также поместите тесты для таких событий, как зависание, и в этом случае вы прекратите свою подпрограмму.
Существует ряд реализаций в открытом доступе, и некоторые операционные системы (например, Windows) предлагают сопутствующие услуги. Просто Google для совместной рутины или волокна.