2012-01-08 3 views
1

У меня есть ситуация, когда у меня есть один объект-эмиттер и набор приемников. Приемники имеют один и тот же класс и фактически представляют собой набор устройств того же типа. Я использую структуру Qt.Динамическое изменение сигнала одному объекту в наборе

  • Сам эмиттер получает сигнал, запрашивающий информацию с одного из устройств.

  • В соответствующем слоте эмиттер должен проверить, какой из приемников «готов», а затем отправить собственный сигнал для запроса данных на одно из устройств (в зависимости от того, что готово в первую очередь).

Излучатель получает сигналы очень быстро, порядка миллисекунд. Есть три способа, которыми я могу думать о безопасном запросе данных только с одного из устройств (устройства живут в своих потоках, поэтому мне нужен механизм, защищенный потоками). Количество устройств не является статическим и может меняться. Общее количество устройств довольно невелико (определенно ниже 5-6).

1) Подключайтесь ко всем устройствам при их добавлении или удалении. Измените один запрос и сами объекты устройств отфильтровывают, является ли запрос для них использованием определенного тега устройства. Этот метод хорош, потому что слот запроса, в котором происходит проверка, будет выполняться в контексте выделенного потока, но расточительно по мере увеличения количества устройств.

2) Подключайте и отсоединяйте от объекта внутри излучателя на лету, когда необходимо отправить запрос.

3) Используйте QMetaObject :: invokeMethod(), когда необходимо отправить запрос.

Эксплуатация важна. Кто-нибудь знает, какой метод является «лучшим», или вообще есть лучший?

С уважением

Pris

Примечание: Для уточнения: Излучатель получает сигнал из приложения, чтобы получить информацию, опрашивая устройства. Сумасшедший ASCII искусство идут:

(приложение) < ----> (эмиттер) < ------> (приемники) < - | -> физические устройства

ответ

0

На основании информации, которую вы я бы по-прежнему рекомендовал реализацию Reactor. Если вы не используете ACE, вы можете реализовать свои собственные. Базовая архитектура выглядит следующим образом:

  1. select, чтобы проснуться, когда сигнал или данные получены из приложения.
  2. Если сокет готов на передающий список, то вы просто выбрать один и отправить его данные
  3. Когда данные посылаются Receiver удаляет себя из множества гнезд/обработчиков, которые доступны
  4. Когда данные обрабатываются Reciever перерегистрируется в список доступных получателей.

Поэтому я предложил ACE потому, что она имеет один из самых простых в использовании реализаций Reactor шаблона.

+0

Я сформулировал вопрос плохо и обновил его, чтобы уточнить точку. 1) Да, но сейчас я беспокоюсь только о потоке сигнала от приложения к приемникам. 2) приемники идентичны, но не делят данные. ACE кажется, что это может быть слишком велико для этого. – Prismatic

+0

@Pris Reactor все равно будет работать, даже если это не с 'ACE'. Я настраиваю ответ. – Karlson

0

Я занимаюсь здесь многопотоковой средой.

Если вы ограничены системой сигналов/слотов Qt между тогдашним ответом на конкретные вопросы:

1), безусловно, не путь. При испускании из Emitter общее количество событий, равных числу Receivers, будет помещено в очередь для циклов событий (ов) потоков (ов), то такое же количество вызовов слотов произойдет, когда поток (ы) достигнут этого события , Даже если большая часть потерянных только if(id!=m_id) return; на их первой линии, ее значительное количество вещей происходит в ядре Qt. Поместите точку останова в один из ваших слотов, который вызывается сигналом Qt::QueuedConnection и подтвердите это, глядя на фактическую трассировку стека. Обычно он, по крайней мере, 4 набирает глубину от xyEventLoop::processEvents(...), поэтому «просто возвращение» определенно не «свободно» с точки зрения времени.

2) Не уверен, что внутренняя реализация Qt на самом деле есть, но из того, что я знаю, подключение и отключение, скорее всего, включают вставку и удаление отправителя и получателя в некоторые списки, к которым, скорее всего, обращаются с блокировкой QMutex. - также может быть «дорогостоящим» по времени, а быстрое соединение и разъединение - определенно не лучшая практика.

3) Возможно, самое меньшее «дорогое временное» решение, которое вы можете найти, которое по-прежнему использует систему сингл-слотов Qt.

опционально) Посмотрите на QSignalMapper. Он разработан именно для того, что вы планировали сделать в варианте 1).

Существует более оптимальное решение для связи между вашими Emitter и Receivers, но, как наилучшая практика, я бы выбрал наиболее простой в использовании и быстро реализуемый вариант, но у него есть шанс на достаточно быструю работу, (это вариант 3).). Затем, когда это будет сделано, проверьте, соответствует ли оно вашим требованиям к производительности. Если это не так, и только тогда, рассмотрите возможность использования разделяемой памяти с мьютексами в поставщике данных - архитектуре потребительской информации (Emitter), чтобы быстро отправлять данные запроса в круговом списке, в то время как нитки (нити) Receiver читают их каждый раз, когда есть время, а затем публикуют результаты возвращаются аналогичным образом, а нить Emitter постоянно опросает сделанные результаты.)

Смежные вопросы