Реализация конечного автомата в C - PullRequest
0 голосов
/ 04 мая 2018

Я пытался реализовать конечный автомат на языке C, и я не уверен, что моя реализация уместна. Я попытался реализовать диаграмму состояний в псевдообъектной манере. Поэтому я объявил открытый интерфейс StateMachine "class" в заголовочном файле StateMachine.h:

typedef enum{
  STATE_01,
  STATE_02,
  STATE_03,
  STATE_04
}state_e;

typedef enum{
  NO_EVENT,
  EVENT_01,
  EVENT_02,
  EVENT_03,
  EVENT_04,
  EVENT_05,
  EVENT_06,
  EVENT_07
}event_e;

// state machine instance
typedef struct{
  state_e currState;
}StateMachine;

extern void InitState(StateMachine*);
extern void ProcSTATE_01(StateMachine*, event_e);
extern void ProcSTATE_02(StateMachine*, event_e);
extern void ProcSTATE_03(StateMachine*, event_e);
extern void ProcSTATE_04(StateMachine*, event_e);
extern void ProcEvent(StateMachine*, event_e);

Реализация "методов" объекта StateMachine находится в модуле StateMachine.c:

void InitState(StateMachine *sm)
{
    sm->currState = STATE_01;
}


void ProcSTATE_01(StateMachine *sm, event_e event)
{
  if(event == EVENT_01){
    sm->currState = STATE_02;
  }
}

void ProcSTATE_02(StateMachine *sm, event_e event)
{
  // ...
}

void ProcSTATE_03(StateMachine *sm, event_e event)
{
  // ...
}

void ProcSTATE_04(StateMachine *sm, event_e event)
{
  // ...
}


void ProcEvent(StateMachine *sm, event_e event)
{
    switch(sm->currState){
      case STATE_01:
        ProcSTATE_01(sm, event);
      break;

      case STATE_02:
        ProcSTATE_02(sm, event);
      break;

      case STATE_03:
        ProcSTATE_03(sm, event);
      break;

      case STATE_04:
        ProcSTATE_04(sm, event);
      break;

    }
}

Использование объекта StateMachine следующее:

int main(int argc, char** argv) {

    StateMachine app;
    ProcEvent(&app, EVENT_01);

    return 0;
}

Я хотел бы спросить любого более опытного, может ли он увидеть какие-либо потенциальные проблемы, связанные с этой реализацией. Спасибо за любые комментарии.

Ответы [ 2 ]

0 голосов
/ 21 июня 2018

Не существует «правильного» способа реализации конечного автомата (как, например, подход таблицы состояний, упомянутого Дагом), но есть код, который может дать вам прямое представление о том, что легко использовать, а что нет. Существует книга Миро Самека об использовании иерархических конечных автоматов в c / c ++. Там он сравнивает различные стили с разработанным им стилем конечного автомата. И я должен сказать, что его стиль является наиболее разумным и понятным для меня. Часть книги также доступна онлайн на state-machine.com. Ваш скелет конечного автомата на самом деле очень похож на часть конечного автомата в подходе Мироса, его подход также добавляет возможность иерархического перехода, очереди на конечный автомат, механизм системных тиков, повторное использование событий, политику копирования с нулевым числом событий и так далее. Если вы посмотрите на его веб-сайт, то увидите, что ваш подход хорош, и его можно расширить многими, многими способами.

0 голосов
/ 04 мая 2018

Вам нужно подумать о том, откуда берутся ваши события. Они генерируются только от самих обработчиков переходов состояний или являются экзогенными. Если они являются экзогенными, то вам, вероятно, понадобится внешний для вашего обработчика цикл событий, который извлекает события из очереди и вставляет их в соответствующий обработчик (который может поставить другое событие в очередь для последующей обработки). Кроме того, вы можете захотеть хранить ваши функции обработчика событий состояния в массиве (индексированном по номеру состояния), чтобы вы могли программно вызывать их (вместо необходимости иметь гигантский оператор switch).

...