Перейти к содержанию
    

Инкрементирующийся define

gdb + eclipse.

 

Понятно. Я всегда говорил, что языки это эхо средств редактирования и отладки.

А вот в IAR и Keil применение enum будет неудобным.

Я, кстати, enum уже давно не применяю. Одни проблемы от них.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что говорит о том, что решение поставленной задачи только с помощью конечного автомата зашло в тупик :(.

Можно сделать завуалированный конечный автомат, без огромных перечислений enum. На стеке.

Будет что-то типа задачи со своим стеком, очередное состояние - это собственно адрес. Вход в автомат - это переключение на его стек, выход (там где был break) - обратное переключение на исходный стек.

Очень удобно отлаживать. Но конечно требуется некоторая дополнительная память (стек).

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Где же тут удобство?

Вижу только проблемы для статического анализатора.

Хранение состояний в стеке приведет к тому что в окне отладчика для переменных они будут большую часть времени не видны.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Где же тут удобство?

Вижу только проблемы для статического анализатора.

Хранение состояний в стеке приведет к тому что в окне отладчика для переменных они будут большую часть времени не видны.

А зачем их видеть? Очередное состояние автомата - это собственно начало очередного участка кода.

Если Вам (для отладки) нужно видеть состояние автомата в моменты выполнения кода за пределами кода автомата, то в функции-переключателе контекста можете сохранить адрес в любую переменную.

Удобство в том хотя-бы, что код линеен, а не вермишель из case ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А зачем их видеть? Очередное состояние автомата - это собственно начало очередного участка кода.

Если Вам (для отладки) нужно видеть состояние автомата в моменты выполнения кода за пределами кода автомата, то в функции-переключателе контекста можете сохранить адрес в любую переменную.

Удобство в том хотя-бы, что код линеен, а не вермишель из case ...

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

Т.е. часть логики кода отнесена куда-то в таблицы.

А это еще хуже вермишели для понимания работы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прямо сейчас у меня в работе протокол с 41-им case в парсере.

В Вашим? Да хоть 4141 case. Это ВАША РЕАЛИЗАЦИЯ некоего протокола, которая делатся через ... Попытайтесь найти спецификацию протокола в котором используется такое количество СОСТОЯНИЙ хоть на каком-то уровне.

Протоколы только отладчиком через SWD и можно детально отладить.

... поехав на край земли с "отладчиком" и сидя на столбе выяснять что это, вдруг, от того, что на противоположном конце земли кто-то, например, заапгрейдил Cisco не может связаться с Магаданом. Да, да внутрисхемный отладчик это очень "полезная" штука в таких ситуациях :).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Т.е. часть логики кода отнесена куда-то в таблицы.

А это еще хуже вермишели для понимания работы.

Примерно так (код вне к.автомата - там где у ТС switch; код автомата - набор case-участков состояний к.автомата):

1. Выполняется код вне к.автомата. На месте switch() ставим переключение контекста на отдельный стек (в стеке сохранён контекст задачи автомата со всеми сохранёнными регистрами и адресом возврата).

SwitchContext(адрес_структуры_контекста_со_стеком).

Внутри функции SwitchContext() сохраняем текущий контекст на текущем стеке, переключаемся на стек к.автомата, восстанавливаем контекст из него и осуществляем возврат в код к.автомата.

В коде к.автомата, выполнив очередную ветку case, опять вызываем SwitchContext(), которая сохранит контекст к.автомата на его стеке, переключится на исходный стек задачи, вызвавшей к.автомат и восстановит контекст из него и осуществит возврат.

Код к. автомата будет выглядеть:

код  //STATE_0
...    //STATE_0
SwitchContext(); //к.автомат перешёл в сост.1 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код  //STATE_1
...    //STATE_1
SwitchContext(); //к.автомат перешёл в сост.2 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код    //STATE_2
...      //STATE_2
if () { //STATE_2
  SwitchContext(); //к.автомат перешёл в сост.3 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
  код    //STATE_3
  ...      //STATE_3
} else {
  SwitchContext(); //к.автомат перешёл в сост.4 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
  код    //STATE_4
  ...      //STATE_4
}
SwitchContext(); //к.автомат перешёл в сост.5 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код    //STATE_5
...      //STATE_5
...

Как видите - код к.автомата получается линейным и легко читаемым даже при наличии ветвлений. А в традиционной реализации к.автомата при неск. ветвлениях по состояниям автомата уже получится малочитаемый вермишельный код.

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

сост0

сост1

сост10

сост11

сост12

сост2

...

сост5

сост6

сост10

сост11

сост12

сост7

...

В традиционной реализации придётся ещё куда-то сохранять/восстаналивать состояния автомата. И вообще получится лес.

А с переключением контекста, будет просто вызов функции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно сделать завуалированный конечный автомат, без огромных перечислений enum....

Уменьшение количества состояний чаще всего достигаеся увеличенем количества автоматов. Все сколь-нибудь вменяемые протоколы разбиты на уровни и обслуживаются на каждом уровне своими автоматоми. Если безмозгло свалить все уровни в одну кучу, то получим именно катострофический рост состояний при котором "41 case" от AlexandrY и "100" от Alt.F4 это даже еще не цветочки :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Уменьшение количества состояний чаще всего достигаеся увеличенем количества автоматов. Все сколь-нибудь вменяемые протоколы разбиты на уровни и обслуживаются на каждом уровне своими автоматоми. Если безмозгло свалить все уровни в одну кучу, то получим именно катострофический рост состояний при котором "41 case" от AlexandrY и "100" от Alt.F4 это даже еще не цветочки :)

Это да, можно и так.

Но бывают даже относительно короткие автоматы в 10-20 состояний, но со сложной логикой ветвления, условными переходами между состояниями или необходимостью выполнения повторяющихся цепочек состояний в разных местах автомата.

Я не говорю конкретно про разбор кадров протокола, вопрос был общего плана об к.автоматах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зря не смотрели в сторону

http://dunkels.com/adam/pt/index.html

и enum не нужны

Protothread это не про протоколы.

Поскольку там используется много неявных выходов из функции, то в сложных десериализаторах придется много кода потратить на сохранение контекста.

Поскольку контекст десереализации не ограничивается только номером состояния как в Protothread.

По мне лучше уж goto чем такие хитрые переходы.

 

код  //STATE_0
...    //STATE_0
SwitchContext(); //к.автомат перешёл в сост.1 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код  //STATE_1
...    //STATE_1
SwitchContext(); //к.автомат перешёл в сост.2 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код    //STATE_2
...      //STATE_2
if () { //STATE_2
  SwitchContext(); //к.автомат перешёл в сост.3 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
  код    //STATE_3
  ...      //STATE_3
} else {
  SwitchContext(); //к.автомат перешёл в сост.4 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
  код    //STATE_4
  ...      //STATE_4
}
SwitchContext(); //к.автомат перешёл в сост.5 (и вышел из контекста к.автомата вернувшись в контекст вызывающей функции)
код    //STATE_5
...      //STATE_5
...

В вашем псевдокоде я вижу только множественные SwitchContext() без аргументов. Это выглядит как полная бессмыслица.

Стек - это в вашем понятии стековая структура данных или стек процессора?

Стековые структуры обычно применяют для раскрытия рекурсии в парсерах. У меня так работают парсеры JSON, LUA и еще несколько.

 

Но в протоколах нет рекурсий. Там есть именно разбор вариантных хидеров. Ничего лучше case для этого не придумано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Protothread это скрытый switch без enum и прочей ерунды.

Контекст всегда можно сделать структурой и устанавливать указатель при входе.

Ограничение только на динамические переменные.

Смысл простой - использование __LINE__ для автогенерации switch/case

Всё остальное - как угодно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Смысл простой - использование __LINE__ для автогенерации switch/case

Да понятен там смысл.

Но влетать внутрь цикла, дескать C-и позволяет это хуже чем goto.

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

 

TC же показал способ с вычисляемыми ключами. Ему Protothread никак не подойдет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но бывают даже относительно короткие автоматы в 10-20 состояний, но со сложной логикой ветвления, условными переходами между состояниями или необходимостью выполнения повторяющихся цепочек состояний в разных местах автомата.

Несомненно! По этой причине я тоже с самого начала писал, что просто не надо все всегда ТОЛЬКО на состояния автомата валить. В каждом конкретом случае надо смотреть, как разгружать собственно автомат от излишества состояний, ибо конечный автомат не есть панацея :(. Совсем недавно в казалось-бы простой задаче начал в лоб писать автомат - началось погружение в пучину состояний. Разбил на два автомата - тоже не сильно понравилось, ибо такой подход нормально работает, когда протокол на уровни бьется. В результате был сделан один автомат на 13 состояний и три бита дополнительных глобальных статусов.

Но в протоколах нет рекурсий...

Это просто Ваши познания в протоколах невелики :(. В тех же телекомуникационных протоколах в полученном фрейме может находится, или не находится, самая разнообразная информация. Причем, как относящаяся к одному объекту, так и к разным. А сам фрейм собираться из множества небольших кусочков. Вот и начинается рекурсивный разбор полей.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это просто Ваши познания в протоколах невелики :(. В тех же телекомуникационных протоколах в полученном фрейме может находится, или не находится, самая разнообразная информация. Причем, как относящаяся к одному объекту, так и к разным. А сам фрейм собираться из множества небольших кусочков. Вот и начинается рекурсивный разбор полей.

Вы уж определитесь о чем хотите рассказать.

Сначала у вас многоуровневые концепции, теперь опять рекурсивные.

 

Фреймы из кусочков это связные списки, а не стековые структуры.

Я не видел рекурсию на в TCP/IP, ни в Zigbee, ни в BLE, ни в USB... Ну ни где.

А вы где усмотрели?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...