LINUX.ORG.RU

Qt отправка сигнала только одному получателю.

 


0

1

Всем привет. Не могу придумать как лучше решить такую задачу на Qt-шных сигналах. Есть объект-обработчик данных и четыре поставщика. Обработчик живет на главном потоке, поставщики каждый на своем Qthread (итого 5 потоков). Поставщик передает запрос обработчику с помощью сигнала, а обработчик возвращает результат, только когда получит запрос еще от одного поставщика (пришла пара - можно посчитать результат и отдать каждому свой). Поставщик не знает, придет он первым или вторым, поэтому сигнал один и тот же. Вопрос в том, как лучше передавать результат обработки поставщику (и первому и второму). Сигнал получают все, кто подписан, а мне нужно, чтобы первый получил сигнал со своими данными, а второй со своими. Остальные два поставщика вообще не должны в этом участвовать.

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

Сделал решение в котором у поставщика есть отдельный метод, эмитирующий сигнал, а в конструкторе объекта-поставщика он сам себя подключает к этому сигналу. Но, возможно, есть решение лучше.


никак. смирись и юзай идентификатор по которому получатель определяет ему ли результат.

MikeDM ★★★★★ ()

А сигналы вообще обязательны? invokeMethod не подойдет? Просто вызываешь слоты напрямую для каждого поставщика со своими данными.

anonymous ()
typedef enum
{
   E_AJ,
   E_Twi,
   E_PDP
} Ponies;
signals:
   void MyLittleSignal(Ponies receiver, char * data);
public slots:
   void Twilight(Ponies receiver, char * data); 
   void Pinkie(Ponies receiver, char * data); 
   void AJ(Ponies receiver, char * data); 
void Twilight(Ponies receiver, char * data)
{
   if (receiver == E_Twi)
   {
      ...
   }
}

void Pinkie(Ponies receiver, char * data)
{
   if (receiver == E_PDP)
   {
      ...
   }
}

void AJ(Ponies receiver, char * data)
{
   if (receiver == E_AJ)
   {
      ...
   }
}
sambist ★★ ()
Ответ на: комментарий от sambist

К чему эти извраты? Почему блин тупо не вызвать эти методы руками, только с разными данными, без извращений с сигналами? Напрямую?

anonymous ()
Ответ на: комментарий от anonymous

invokeMethod не подойдет?

Похоже, подойдет. Не знал про него.

x_hash ()
Ответ на: комментарий от anonymous

Почему блин тупо не вызвать эти методы руками, только с разными данными, без извращений с сигналами? Напрямую?

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

При обмене сигналами код каждого объекта существенно однопоточный.

P.S. Или я что-то не так понял?

x_hash ()
Последнее исправление: x_hash (всего исправлений: 1)
Ответ на: комментарий от x_hash

Ну дык, поэтому я и сказал глядеть в сторону invokeMethod. Там третьим параметром идет Qt::ConnectionType, как и в connect. Используй Qt::QueuedConnection - и будет тебе счастье.

anonymous ()
Ответ на: комментарий от anonymous

только инвоукМетод противоречит концепции слотов-сигналов (интерфейсов) и ведет к лапше, т.к. требуется информация об объекте метод которого вызывается. Я бы передавал из постановщика данные вместе с уникальным идентификатором (guid). И при накоплении необходимых данных в обработчике эмитировал по сигналу на идентификатор, естественно передавая соответствующие данным guid.

anonymous ()
Ответ на: комментарий от anonymous

Дык, о том и речь, что тут эта концепция на хрен не нужна вообще. Тут нужно вызывать для конкретных потоков конкретные слоты в конкретном порядке.

anonymous ()

тут нужен не publisher-subscriber, а какой-нить channel.

т.е. просто на каждый тред сделай объект с сигналом reply, и подпишись на него в нитях

anonymous ()
Ответ на: комментарий от anonymous

т.е. просто на каждый тред сделай объект с сигналом reply, и подпишись на него в нитях

Сделать кроме объекта обработчика еще 4 дополнительных объекта, которые лишь будут отправлять сигнал в нужный поток? Я примерно так и сделал, сигнал сам себе отправляет объект-поставщик, т.е. эти спец-объекты, отправляющие сигнал replay - это сами объекты-поставщики в 4-х потоках (у них есть метод, который только посылает сигнал, а подписываюсь я на этот сигнал в конструкторе).

x_hash ()

Поставщик обработчику отдаёт кроме данных ещё и функтор, котрый эмитирует сигнал, присоединённый к слоту соответствующего поставщика (queued connection). Когда данные пришли - обработчик вызывает функторы обротанных данных и севупле например.

nanoolinux ★★★★ ()
Ответ на: комментарий от nanoolinux

Поставщик обработчику отдаёт кроме данных ещё и функтор, котрый эмитирует сигнал...

Ага, так тоже можно. К тому же этот вариант не создает лапши вместо интерфейса.

x_hash ()

А sender() никак нельзя использовать?

Adonai ★★★ ()
Ответ на: комментарий от Torvus

Я так и не понял, как с ними работать. Предопределенные ивенты, это что-то типа нажали кнопку мыши, а вот получится ли сделать сколько угодно своих типов событий, и как совместить обработку определенных пользователем событий, если я пишу библиотеку, а ее использует приложение, которое тоже создаст собственные ивенты, так сразу неясно (нужно разбираться). К тому же ивенты обрабатываются в одном методе, и в нем придется писать свой диспетчер всех типов событий, которые меня интересуют. Наверное, это очень просто, но с сигналами еще проще, их куда подключишь - в тот метод они и приходят.

В общем, возможно, ивенты подходящий вариант, но с ним нужно разбираться.

x_hash ()
Ответ на: комментарий от x_hash

И все же советую почитать про эвенты. Это не сложно. Сигналы в Qt, конечно, сделаны удобно, но всему свое место

Torvus ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.