Russian Qt Forum
Ноябрь 23, 2024, 19:20 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Замена switch  (Прочитано 4735 раз)
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« : Июнь 27, 2012, 12:40 »

Есть почти классическая задача - TCP получает сервер вынимает из QTcpSocket заголовок сообщения, в нём получает некий id сообщения и должен вызвать соответсвующий обработчик. Сейчас это реализовано через длинный switch вида
Код
C++ (Qt)
 
   switch (header->id) {
   case ind::Start:
       emit start(header->data);
       break;
   }
   case ind::Stop:
       emit stop(header->data);
       break;
   }
   case ind::Pause:
       emit pause(header->data);
       break;
   }
   default:
       qWarning() << tr("Unknown command: id = %1, size = %2").arg(header->id).arg(header->data->size));
   }
 

По понятным архитектурным причинам (очень уж switch длинный, плохо расширяемый и т.п.) хотелось бы уйти от этого switch в пользу, например, хеша с ключами в виде enum и значениями в виде сигналов. Т.е. case будет заменен на нечто подобное:
Код
C++ (Qt)
 
if (m_hash.contains(header->id))
   QMetaObject::invokeMethod(this, m_hash.value(header->id), QT_ARG(QByteArray, header->data));
 
Какие недостатки у такого решения, кроме неизбежных накладных расходов на косвенный вызов методов? Какие еще есть варианты ухода от длинного switch?
Записан
alexis031182
Гость
« Ответ #1 : Июнь 27, 2012, 12:53 »

...
Какие недостатки у такого решения, кроме неизбежных накладных расходов на косвенный вызов методов? Какие еще есть варианты ухода от длинного switch?
А разве в switch у Вас не тоже самое делается, что и в случае с invokeMethod? Такой же "косвенный" вызов только через emit. Рекомендую на сервере отказаться от использования сигнал/слотов, если Вам нужна скорость. Впрочем, если Вы используете QTcpServer, то моя рекомендация не имеет ценности, конечно Улыбающийся

А вообще, задействуйте фабрику методов. Тот же QMetaType существенно универсализирует код.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #2 : Июнь 27, 2012, 13:03 »

Можно хранить константный массив указателей на обработчики методов типа start, pause ...,
где итераторами массива будут значения id, (с условием, что они с нуля начинаются) тогда переписать можно так:

Код
C++ (Qt)
typedef MyHandler ... *handler(...);
 
static const MyHandler table[3] = { start, stop, pause };
 
...
emit table[header->id](header->data);
...
 
 

Как то так.. Улыбающийся
Записан

ArchLinux x86_64 / Win10 64 bit
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Июнь 27, 2012, 13:16 »

Какие недостатки у такого решения, кроме ..
Ощутимым может оказаться затруднение отладки, нужно как-то прорваться в invoke чтобы понять что вызывается
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #4 : Июнь 27, 2012, 13:17 »

Рекомендую на сервере отказаться от использования сигнал/слотов, если Вам нужна скорость.
Отказаться в пользу чего?

Впрочем, если Вы используете QTcpServer, то моя рекомендация не имеет ценности, конечно Улыбающийся
Дело в том, что сервер у меня не очень классический. Максимальное одновременное количество клиентов - не более 256, обычно - до 8. Но каждый из клиентов для сервера достаточно "прожорлив" как по памяти, так и по вычислительной нагрузке, при этом поток управляющих воздействий от клиента на сервер невелик (по сути - трансляция пользовательского интерфейса), а вот от сервера к клиенту трафик достаточно велик (по структуре похож на видео сигнал). До сих пор возможностей QTcpServer с большим запасом хватало, но сейчас есть разрабатывается новая версия и есть возможность уйти к чему-нибудь другому. Вопрос - к чему и ради чего?
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #5 : Июнь 27, 2012, 13:19 »

Ощутимым может оказаться затруднение отладки, нужно как-то прорваться в invoke чтобы понять что вызывается
С этим готов мириться
Записан
alexis031182
Гость
« Ответ #6 : Июнь 27, 2012, 13:28 »

Отказаться в пользу чего?
Сигнал/слоты - очень удобное решение, но медленнее, нежели прямой вызов функций. Это известно.

Дело в том, что сервер у меня не очень классический. Максимальное одновременное количество клиентов - не более 256, обычно - до 8. Но каждый из клиентов для сервера достаточно "прожорлив" как по памяти, так и по вычислительной нагрузке, при этом поток управляющих воздействий от клиента на сервер невелик (по сути - трансляция пользовательского интерфейса), а вот от сервера к клиенту трафик достаточно велик (по структуре похож на видео сигнал). До сих пор возможностей QTcpServer с большим запасом хватало, но сейчас есть разрабатывается новая версия и есть возможность уйти к чему-нибудь другому. Вопрос - к чему и ради чего?
Если возможностей QTcpServer достаточно, то
... то моя рекомендация не имеет ценности, конечно Улыбающийся
Если у Вас малое количество соединений, малый входящий трафик и исходящий, хотя и тяжёлый, но не особо критичен ко скорости отдачи, то по идее QTcpServer - нормальное решение.
Записан
DmitryM
Гость
« Ответ #7 : Июнь 28, 2012, 10:13 »

map с lambda функциями.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.104 секунд. Запросов: 23.