Реализация иерархических конечных автоматов на C

Я немного не понимаю, как реализовать мои конечный автомат.
Я уже знаю, что он иерархический, поскольку некоторые состояния используют одно и то же действие.
Я определяю, что мне нужно делать, с помощью следующих параметров:

  • Class (Значения: Base , Derived , Specific )
  • OpCode
  • Параметр 1 - необязательный
  • Параметр 2 - необязательный

My иерархия определяется классом, а код операции представляет действие.
Производный может использовать OpCodes из Base и Specific ] может использовать OpCodes обоих Base ] и Получено .
Наивная реализация заключается в следующем:

void (*const state_table [MAX_CLASSES][MAX_OPCODES]) (state *) {
  {base_state1, base_state2, NULL, NULL},
  {base_state1, base_state2, derived_state1, NULL},
  {base_state1,base_state2, derived_state1, specific_state3},
};

void dispatch(state *s)
{
  if (state_table[s->Class][s->OpCode] != NULL)
    state_table[s->Class][s->OpCode](s);
}

Это очень быстро станет недоступным для обслуживания.
Есть ли другой способ сопоставить состояние с суперклассом?

РЕДАКТИРОВАТЬ:
Дальнейшие вычисления наводят меня на мысль, что я, вероятно, буду использовать большинство, если не все OpCodes , но я не буду использовать все доступные мне классы .
Другое пояснение:
Некоторые операционные коды могут совместно использоваться несколькими производными и базовыми классами .
Например:

  • У меня есть класс с именем Any , который является базовым классом. Он имеет коды операций : STATE_ON , STATE_OFF , STATE_SET .
  • У меня есть еще один класс под названием MyGroup , который является производным классом. Он имеет OpCodes : STATE_FLIP , STATE_FLOP .

  • Третий класс - это специальный класс с именем ThingInMyGroup , который имеет код операции : STATE_FLIP_FLOP_AND_FLOOP .

Таким образом, сообщение с классом Any отправляется с сервера, принимается всеми клиентами и обрабатывается.

Сообщение с классом MyGroup отправляется с сервера, принимается всеми клиентами и обрабатывается только на клиентах, принадлежащих к MyGroup , любым OpCodes , которые являются допустимы для Любые классы допустимы для класса MyGroup .

Сообщение с классом ThingInMyGroup отправляется с сервера, принимается всеми клиентами и обрабатывается только на клиентах, которые принадлежат к MyGroup и являются ThingInMyGroup *, любой * * Коды операций , действительные для класса Any и класса MyGroup , действительны для класса ThingInMyGroup .

После того, как сообщение получено, клиент соответственно ACK / NACK.

Я предпочитаю не использовать варианты переключения или константные массивы, так как они станут недоступны для обслуживания, когда станут больше.
Мне нужен гибкий дизайн, который позволяет мне:

  1. Чтобы указать, какие коды операций доступны для каждого класса .
  2. Чтобы указать суперкласс для каждого класса и через эту спецификацию, чтобы я мог вызвать указатель функции, который представлен текущим OpCode .
5
задан the_drow 18 August 2010 в 11:22
поделиться