AlexandrY 3 10 июля, 2016 Опубликовано 10 июля, 2016 · Жалоба gdb + eclipse. Понятно. Я всегда говорил, что языки это эхо средств редактирования и отладки. А вот в IAR и Keil применение enum будет неудобным. Я, кстати, enum уже давно не применяю. Одни проблемы от них. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 10 июля, 2016 Опубликовано 10 июля, 2016 · Жалоба Что говорит о том, что решение поставленной задачи только с помощью конечного автомата зашло в тупик :(. Можно сделать завуалированный конечный автомат, без огромных перечислений enum. На стеке. Будет что-то типа задачи со своим стеком, очередное состояние - это собственно адрес. Вход в автомат - это переключение на его стек, выход (там где был break) - обратное переключение на исходный стек. Очень удобно отлаживать. Но конечно требуется некоторая дополнительная память (стек). Я так иногда делаю когда автомат получается ну очень сложным, да ещё с вложенными ветками. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 10 июля, 2016 Опубликовано 10 июля, 2016 · Жалоба Я так иногда делаю когда автомат получается ну очень сложным, да ещё с вложенными ветками. Где же тут удобство? Вижу только проблемы для статического анализатора. Хранение состояний в стеке приведет к тому что в окне отладчика для переменных они будут большую часть времени не видны. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 60 10 июля, 2016 Опубликовано 10 июля, 2016 · Жалоба Зря не смотрели в сторону http://dunkels.com/adam/pt/index.html и enum не нужны Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 10 июля, 2016 Опубликовано 10 июля, 2016 · Жалоба Где же тут удобство? Вижу только проблемы для статического анализатора. Хранение состояний в стеке приведет к тому что в окне отладчика для переменных они будут большую часть времени не видны. А зачем их видеть? Очередное состояние автомата - это собственно начало очередного участка кода. Если Вам (для отладки) нужно видеть состояние автомата в моменты выполнения кода за пределами кода автомата, то в функции-переключателе контекста можете сохранить адрес в любую переменную. Удобство в том хотя-бы, что код линеен, а не вермишель из case ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 11 июля, 2016 Опубликовано 11 июля, 2016 · Жалоба А зачем их видеть? Очередное состояние автомата - это собственно начало очередного участка кода. Если Вам (для отладки) нужно видеть состояние автомата в моменты выполнения кода за пределами кода автомата, то в функции-переключателе контекста можете сохранить адрес в любую переменную. Удобство в том хотя-бы, что код линеен, а не вермишель из case ... Хоть я и не совсем понимаю о чем вы говорите, поскольку не видно кода, но могу уверенно сказать, что ваш код не линейный, а размазанный. Т.е. часть логики кода отнесена куда-то в таблицы. А это еще хуже вермишели для понимания работы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 11 июля, 2016 Опубликовано 11 июля, 2016 · Жалоба Прямо сейчас у меня в работе протокол с 41-им case в парсере. В Вашим? Да хоть 4141 case. Это ВАША РЕАЛИЗАЦИЯ некоего протокола, которая делатся через ... Попытайтесь найти спецификацию протокола в котором используется такое количество СОСТОЯНИЙ хоть на каком-то уровне. Протоколы только отладчиком через SWD и можно детально отладить. ... поехав на край земли с "отладчиком" и сидя на столбе выяснять что это, вдруг, от того, что на противоположном конце земли кто-то, например, заапгрейдил Cisco не может связаться с Магаданом. Да, да внутрисхемный отладчик это очень "полезная" штука в таких ситуациях :). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 11 июля, 2016 Опубликовано 11 июля, 2016 · Жалоба Хоть я и не совсем понимаю о чем вы говорите, поскольку не видно кода, но могу уверенно сказать, что ваш код не линейный, а размазанный. Т.е. часть логики кода отнесена куда-то в таблицы. А это еще хуже вермишели для понимания работы. Примерно так (код вне к.автомата - там где у ТС 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 ... В традиционной реализации придётся ещё куда-то сохранять/восстаналивать состояния автомата. И вообще получится лес. А с переключением контекста, будет просто вызов функции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 11 июля, 2016 Опубликовано 11 июля, 2016 · Жалоба Можно сделать завуалированный конечный автомат, без огромных перечислений enum.... Уменьшение количества состояний чаще всего достигаеся увеличенем количества автоматов. Все сколь-нибудь вменяемые протоколы разбиты на уровни и обслуживаются на каждом уровне своими автоматоми. Если безмозгло свалить все уровни в одну кучу, то получим именно катострофический рост состояний при котором "41 case" от AlexandrY и "100" от Alt.F4 это даже еще не цветочки :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 11 июля, 2016 Опубликовано 11 июля, 2016 · Жалоба Уменьшение количества состояний чаще всего достигаеся увеличенем количества автоматов. Все сколь-нибудь вменяемые протоколы разбиты на уровни и обслуживаются на каждом уровне своими автоматоми. Если безмозгло свалить все уровни в одну кучу, то получим именно катострофический рост состояний при котором "41 case" от AlexandrY и "100" от Alt.F4 это даже еще не цветочки :) Это да, можно и так. Но бывают даже относительно короткие автоматы в 10-20 состояний, но со сложной логикой ветвления, условными переходами между состояниями или необходимостью выполнения повторяющихся цепочек состояний в разных местах автомата. Я не говорю конкретно про разбор кадров протокола, вопрос был общего плана об к.автоматах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 11 июля, 2016 Опубликовано 11 июля, 2016 · Жалоба Зря не смотрели в сторону 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 для этого не придумано. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 60 11 июля, 2016 Опубликовано 11 июля, 2016 · Жалоба Protothread это скрытый switch без enum и прочей ерунды. Контекст всегда можно сделать структурой и устанавливать указатель при входе. Ограничение только на динамические переменные. Смысл простой - использование __LINE__ для автогенерации switch/case Всё остальное - как угодно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 11 июля, 2016 Опубликовано 11 июля, 2016 · Жалоба Смысл простой - использование __LINE__ для автогенерации switch/case Да понятен там смысл. Но влетать внутрь цикла, дескать C-и позволяет это хуже чем goto. Опять же при символьной отладке это будет выглядеть как хаотичная передача управления непонятно куда. TC же показал способ с вычисляемыми ключами. Ему Protothread никак не подойдет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 11 июля, 2016 Опубликовано 11 июля, 2016 · Жалоба Но бывают даже относительно короткие автоматы в 10-20 состояний, но со сложной логикой ветвления, условными переходами между состояниями или необходимостью выполнения повторяющихся цепочек состояний в разных местах автомата. Несомненно! По этой причине я тоже с самого начала писал, что просто не надо все всегда ТОЛЬКО на состояния автомата валить. В каждом конкретом случае надо смотреть, как разгружать собственно автомат от излишества состояний, ибо конечный автомат не есть панацея :(. Совсем недавно в казалось-бы простой задаче начал в лоб писать автомат - началось погружение в пучину состояний. Разбил на два автомата - тоже не сильно понравилось, ибо такой подход нормально работает, когда протокол на уровни бьется. В результате был сделан один автомат на 13 состояний и три бита дополнительных глобальных статусов. Но в протоколах нет рекурсий... Это просто Ваши познания в протоколах невелики :(. В тех же телекомуникационных протоколах в полученном фрейме может находится, или не находится, самая разнообразная информация. Причем, как относящаяся к одному объекту, так и к разным. А сам фрейм собираться из множества небольших кусочков. Вот и начинается рекурсивный разбор полей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 11 июля, 2016 Опубликовано 11 июля, 2016 · Жалоба Это просто Ваши познания в протоколах невелики :(. В тех же телекомуникационных протоколах в полученном фрейме может находится, или не находится, самая разнообразная информация. Причем, как относящаяся к одному объекту, так и к разным. А сам фрейм собираться из множества небольших кусочков. Вот и начинается рекурсивный разбор полей. Вы уж определитесь о чем хотите рассказать. Сначала у вас многоуровневые концепции, теперь опять рекурсивные. Фреймы из кусочков это связные списки, а не стековые структуры. Я не видел рекурсию на в TCP/IP, ни в Zigbee, ни в BLE, ни в USB... Ну ни где. А вы где усмотрели? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться