Здравствуйте, kvser, Вы писали:
ЮЖ>>Вынести действия в функции.
K>я хочу сказать что не удобно поддерживать одну и туже switch структуру в двух разных местах. К примеру я могу в одном месте добавить case а в другом не добавить его. Как бы можно было сделать так, чтобы я этого не смог забыть?
Если и дальше возиться со switch, то можно его оставить в единственном числе:
Я правильно понимаю что есть две последовательности почти совпадающих обработчиков ? Пока мысли такие:
Напрашивается еще вариант с полиморфными(или boost::function) обработчиками. switch в этом случае можно оставить один для всех сочетаний (функция, подфункция) или преобразовать в ассоциативный массив std::map<(функция, подфункция), handler>
Тут встает вопрос как заполнять два таких массива. "Пересечение" общих обработчиков можно выделить в один массив, и для каждого случая создавать его копию(один раз при запуске) и добавлять специфические для данного потока обработчики. Это позволит локализовать места их добавления.
Тоже самое можно сделать и в compile-time на шаблонах. Будет три специализации(traits): общие обработчики, thread_specific1 и thread_specific2.
Разное поведение в switch при разных контекстах выполнения
Есть поток1 и поток2. Поток1 — генератор команд GUI, поток2 — система передачи команд до цели и получения ответных данных.
В каждой команде указывается адрес устройства, какую функцию и подфункцию должно выполнить устройство и собственно данные для выполнения данной подфункции.
В каждом ответе на команду есть адрес устройства, какую функцию и подфункцию выполнило устройство, признак ответа и собственно данные описывающие результат выполнения. При этом на некоторые команды(когда команда может выполняться продолжительное время) может придти несколько ответов: 1 — ответ о получении команды устройством, 2 — ответ с результатами выполнения по истечении некоторого времени; для чего и служит признак ответа.
Поток1 формирует команды для внешних устройств(исходя из введенных пользователем данных)и обрабатывает ответы (показывает пользователю пришедшие данные в удобном виде).
Поток2 передает команды устройствам (в виде последовательности байт из потока1), получает пришедшие данные(последовательность байт), посылает копию данных потоку1, далее анализирует эти данные(например сравнивает адрес, фукнцию, подфункцию, CRC, признак ответа) и решает:
1) ждать следующего ответа от данного устройства, а статус команды перевести в "Выполняется устройством";
2) пришел окончательный ответ на команды и команду необходимо удалить из очереди
3) Это не ответ на отосланную команду (например после сбоя физической линии передачи), ждать ответа дальше
Поток1, получив данные от потока2, анализирует не только адрес, фукнцию, подфункцию, CRC, признак ответа, но и данные описывающие результат выполнения. Также все переданные данные и пришедшие данные поток1 показывает пользователю в отдельном окне.
Вот тут получается, что при ответе и поток1 и поток 2 фукнцию, подфункцию. А это выглядит так:
switch(байтФункции)
{
case F1:
{
switch(байтПодфункции)
{
case SF1:{...} case SF2:{...}...и т.д.
}
}
...и т.д.
}
Но при этом действия в телах "case SFx" в потоке1 и потоке2 отличаются, т.е. эта функция в потоке2 просто возвращает логическую переменную, что это ответ или не ответ; а в потоке1 эта функция соответствующим кейсу образом обрабатывает в ответе данные результата, после чего результат показывается пользователю в удобном виде.
Дак вот при добавлении/удалении функций и подфункций приходится менять код "switch(байтФункции)" в двух местах, что часто приводит к ошибкам при больших switch. Как можно выполнять различные дествия в case при разном контексте использования? Можно switch заменить чем-то другим, это не важно
Re: Разное поведение в switch при разных контекстах выполнен
Здравствуйте, kvser, Вы писали:
... K>Вот тут получается, что при ответе и поток1 и поток 2 фукнцию, подфункцию. А это выглядит так:
K>
K>switch(байтФункции)
K>{
K> case F1:
K> {
K> switch(байтПодфункции)
K> {
K> case SF1:{...} case SF2:{...}...и т.д.
K> }
K> }
K>...и т.д.
K>}
K>
K>Но при этом действия в телах "case SFx" в потоке1 и потоке2 отличаются, т.е. эта функция в потоке2 просто возвращает логическую переменную, что это ответ или не ответ; а в потоке1 эта функция соответствующим кейсу образом обрабатывает в ответе данные результата, после чего результат показывается пользователю в удобном виде.
K>Дак вот при добавлении/удалении функций и подфункций приходится менять код "switch(байтФункции)" в двух местах, что часто приводит к ошибкам при больших switch. Как можно выполнять различные дествия в case при разном контексте использования? Можно switch заменить чем-то другим, это не важно
Вынести действия в функции. Если значения байтФункции & байтПодфункции представляют собой числа от 0 до 9 то можно прикрутить что-то вроде такого:
#define UNION(A, B) (10*(A) + (B))
switch(UNION(байтФункции, байтПодфункции))
{
case UNION(F1, SF1): return handle_F1_SF1();
case UNION(F1, SF2): return handle_F1_SF2();
//...
}
Если значений больше чем 10, то нужно изменить множитель в UNION.
Так же можно посмотреть в сторону мультиметодов.
Re[2]: Разное поведение в switch при разных контекстах выпол
я хочу сказать что не удобно поддерживать одну и туже switch структуру в двух разных местах. К примеру я могу в одном месте добавить case а в другом не добавить его. Как бы можно было сделать так, чтобы я этого не смог забыть?
#define UNION(A, B) (10*(A) + (B))
Конечно упростит структуру switch(хотя бы не будет вложенного), но при 10*(A) + (B) достигающим 100 и более, сразу и не увидишь присутствует тот или иной case. Хотя поиском по значению А и В можно...но меня больше волнует то, что я могу забыть написать в одном из мест соотвтствующий case, а потом тратить время на поиски баги и, в результате, убедиться, что мои сомнения не напрасны
Re[4]: Разное поведение в switch при разных контекстах выпол
Здравствуйте, kvser, Вы писали:
K>Дак вот при добавлении/удалении функций и подфункций приходится менять код "switch(байтФункции)" в двух местах, что часто приводит к ошибкам при больших switch. Как можно выполнять различные дествия в case при разном контексте использования? Можно switch заменить чем-то другим, это не важно
Например, завести интерфейс обработки команды, с двумя методами -- один для одного контекста, а другой для другого.
И как-то по паре функция-подфункция получать интерфейс (например функцией, внутри которой всё тот же switch), а уж в зависимости от контекста звать нужный метод...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Разное поведение в switch при разных контекстах выполнен
Здравствуйте, kvser, Вы писали:
K>Здравствуйте!
K>Есть поток1 и поток2. Поток1 — генератор команд GUI, поток2 — система передачи команд до цели и получения ответных данных.
K>В каждой команде указывается адрес устройства, какую функцию и подфункцию должно выполнить устройство и собственно данные для выполнения данной подфункции. K>В каждом ответе на команду есть адрес устройства, какую функцию и подфункцию выполнило устройство, признак ответа и собственно данные описывающие результат выполнения. При этом на некоторые команды(когда команда может выполняться продолжительное время) может придти несколько ответов: 1 — ответ о получении команды устройством, 2 — ответ с результатами выполнения по истечении некоторого времени; для чего и служит признак ответа.
K>Поток1 формирует команды для внешних устройств(исходя из введенных пользователем данных)и обрабатывает ответы (показывает пользователю пришедшие данные в удобном виде). K>Поток2 передает команды устройствам (в виде последовательности байт из потока1), получает пришедшие данные(последовательность байт), посылает копию данных потоку1, далее анализирует эти данные(например сравнивает адрес, фукнцию, подфункцию, CRC, признак ответа) и решает: K>1) ждать следующего ответа от данного устройства, а статус команды перевести в "Выполняется устройством"; K>2) пришел окончательный ответ на команды и команду необходимо удалить из очереди K>3) Это не ответ на отосланную команду (например после сбоя физической линии передачи), ждать ответа дальше
K>Поток1, получив данные от потока2, анализирует не только адрес, фукнцию, подфункцию, CRC, признак ответа, но и данные описывающие результат выполнения. Также все переданные данные и пришедшие данные поток1 показывает пользователю в отдельном окне.
K>Вот тут получается, что при ответе и поток1 и поток 2 фукнцию, подфункцию. А это выглядит так:
K>
K>switch(байтФункции)
K>{
K> case F1:
K> {
K> switch(байтПодфункции)
K> {
K> case SF1:{...} case SF2:{...}...и т.д.
K> }
K> }
K>...и т.д.
K>}
K>
K>Но при этом действия в телах "case SFx" в потоке1 и потоке2 отличаются, т.е. эта функция в потоке2 просто возвращает логическую переменную, что это ответ или не ответ; а в потоке1 эта функция соответствующим кейсу образом обрабатывает в ответе данные результата, после чего результат показывается пользователю в удобном виде.
K>Дак вот при добавлении/удалении функций и подфункций приходится менять код "switch(байтФункции)" в двух местах, что часто приводит к ошибкам при больших switch. Как можно выполнять различные дествия в case при разном контексте использования? Можно switch заменить чем-то другим, это не важно
Почему просто не повесить на коды функций и подфункций обработчики, напимер, используя std::map (или несколько) и не придумать механизм их обхода (заменяющий твою комбинацию switch-ей).
Что-то типа map<BYTE, Handlers>, где
struct Handlers
{
IHandler* pThread1Handler;
IHandler* pThread2Handler;
};
Тогда надо будет просто два раза инициализировать этот механизм для потока1 и потока2, а потом при получении команды каждым из них делать что-то типа Run(команда) и все.
Re[2]: Разное поведение в switch при разных контекстах выпол
Здравствуйте, Erop, Вы писали:
E>Например, завести интерфейс обработки команды, с двумя методами -- один для одного контекста, а другой для другого. E>И как-то по паре функция-подфункция получать интерфейс (например функцией, внутри которой всё тот же switch), а уж в зависимости от контекста звать нужный метод...