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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Как проверить, что для данной пары сигнал/слот установлено Qt::DirectConnection?  (Прочитано 10577 раз)
Akon
Гость
« : Сентябрь 01, 2011, 16:51 »

сабж
Записан
ритт
Гость
« Ответ #1 : Сентябрь 01, 2011, 19:38 »

рассоединить и соединить с Qt::DirectConnection ?
а что за юзкейс, позвольте полюбопытсвовать?
Записан
Akon
Гость
« Ответ #2 : Сентябрь 01, 2011, 19:58 »

Из потока прут данные с уведомление по сигналу. Обработка производится синхронно (Qt::DirectConnection) пользовательским объектом, "живущим" в другом потоке. Если опустить параметр соединения, то для данного случая получится Qt::QueudConnection. Задача: предупредить  пользователя (выдать диагностическое сообщение), если он подключится без Qt::DirectConnection (т.е. явно его не укажет).
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #3 : Сентябрь 01, 2011, 20:31 »

В слоте сравнить sender()->thread() c QThread::currentThread(), на всякий случай проверив sender() на 0.
Записан
Akon
Гость
« Ответ #4 : Сентябрь 01, 2011, 21:05 »

sender()->thread() - дает поток, в котором объект "живет"; а сигнал объекта может быть испущен из любого другого потока, и sender()->thread() будет тем же самым.
Записан
ритт
Гость
« Ответ #5 : Сентябрь 01, 2011, 22:17 »

ну, вот и правильно. как Вы выше указали, sender() в днном случае - это поток, из которого "прут данные".
если sender()->thread() == QThread::currentThread() /* равносильно qobject_cast<QThread *>(sender()) == QThread::currentThread() */, значит Qt::DirectConnection; иначе ругаемся

но всё-равно этот юз-кейс какой-то странный...ни разу за свою практику мне не приходилось делать подобных проверок.
и, кстати, в случае неосмотрительности при синхронизации потоков рискуете получить по ушам) я бы советовал использовать здесь Qt::QueuedBlockedConnection /* либо пересмотреть архитектуру приложения */
« Последнее редактирование: Сентябрь 01, 2011, 22:19 от Константин » Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #6 : Сентябрь 01, 2011, 22:32 »

равносильно qobject_cast<QThread *>(sender()) == QThread::currentThread()
Щито?
sender() - это объект испустивший сигнал, он не обязан наследоваться от QThread.
Более того даже у потоков this != this->thread(), за исключением случая использования moveToThread( this ).
Записан
ритт
Гость
« Ответ #7 : Сентябрь 02, 2011, 01:30 »

если наследник QThread испускает сигнал, то равносильно. про moveToThread( this ) всё верно.
Записан
Akon
Гость
« Ответ #8 : Сентябрь 02, 2011, 14:04 »

Цитировать
ну, вот и правильно. как Вы выше указали, sender() в днном случае - это поток, из которого "прут данные".
если sender()->thread() == QThread::currentThread() /* равносильно qobject_cast<QThread *>(sender()) == QThread::currentThread() */, значит Qt::DirectConnection; иначе ругаемся

Равносильно, если наследник QThread испускает сигнал, и для наследника сделано moveToThread( this ).

Пусть источник и приемник сигнала живут в одном потоке. Источник не QThread. В источнике из отдельного внутреннего потока выбрасывается сигнал: Q_EMIT <источник>.someSignal(...).
В слоте при Qt::DirectConnection будет sender()->thread() != QThread::currentThread(), при других типах соединения будет равенство. Но это частный случай: источник и приемник сигнала живут в одном потоке.

Цитировать
но всё-равно этот юз-кейс какой-то странный...ни разу за свою практику мне не приходилось делать подобных проверок.
и, кстати, в случае неосмотрительности при синхронизации потоков рискуете получить по ушам) я бы советовал использовать здесь Qt::QueuedBlockedConnection /* либо пересмотреть архитектуру приложения */

В ситуациях большого объема исходных передаваемых данных, часто использую подобный дизайн в силу его простоты и производительности. После синхронной обработки объем вторичных данных может быть значительно уменьшен, и тут уже к месту Qt::QueuedConnection.

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

Qt::QueuedBlockedConnection - зачастую (практически всегда, когда ждем гуй) убийственная блокировка для источников реального времени.

Записан
ритт
Гость
« Ответ #9 : Сентябрь 03, 2011, 03:39 »

Qt::QueuedBlockedConnection - зачастую (практически всегда, когда ждем гуй) убийственная блокировка для источников реального времени.

если не считать затрат на копирование данных, то более убийственная, чем Qt::DirectConnection между потоками?)
Записан
Akon
Гость
« Ответ #10 : Сентябрь 03, 2011, 06:59 »

Простите, не понял ваш пост.
Записан
ритт
Гость
« Ответ #11 : Сентябрь 03, 2011, 11:53 »

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

в силу implicit sharing природы какого-нибудь QByteArray издержки на копирование оного минимальны и можно условно принять за 0.
очередь данных уже создана и успешно поддерживается за Вас - если не производить никакого колдовства и придерживаться схемы "один обработчик не более чем для одного источника", то последовательность вызовов слота для данных будет совпадать с последовательностью эмитов сигнала с теми же данными. можете убедиться, написав несложный тест.
плюсы очевидны - поток источника данных не занимается чужой работой (а именно, обработкой данных, которая будет выполняться "клиенстким" объектом в своём потоке); и не нужно беспокоиться о межпоточной синхронизации.

Qt::QueuedBlockedConnection - зачастую (практически всегда, когда ждем гуй) убийственная блокировка для источников реального времени.
> если не считать затрат на копирование данных, то более убийственная, чем Qt::DirectConnection между потоками?)

перефразирую: в чём принципиальное отличие Qt::DirectConnection от Qt::QueuedBlockedConnection в задаче, аналогичной Вашей? в чём заключается "убийственная блокировка"?
« Последнее редактирование: Сентябрь 03, 2011, 11:55 от Константин » Записан
Akon
Гость
« Ответ #12 : Сентябрь 03, 2011, 13:28 »

Цитировать
в силу implicit sharing природы какого-нибудь QByteArray издержки на копирование оного минимальны и можно условно принять за 0.
очередь данных уже создана и успешно поддерживается за Вас - если не производить никакого колдовства и придерживаться схемы "один обработчик не более чем для одного источника", то последовательность вызовов слота для данных будет совпадать с последовательностью эмитов сигнала с теми же данными. можете убедиться, написав несложный тест.
плюсы очевидны - поток источника данных не занимается чужой работой (а именно, обработкой данных, которая будет выполняться "клиенстким" объектом в своём потоке); и не нужно беспокоиться о межпоточной синхронизации.

Да, передавать данные посредством implicit sharing или посредством shared pointer очень хороший вариант. При отсутствии специфичных для моей задачи ограничений остановился бы на нем.

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

Теперь рассмотрим клиента, который вычисляет мощность по куску сигнала (т.е. просто получает число) и обновляет прогрессбар. Оптимальным вариантом для клиента будет DirectConnection, синхронное вычисление значения и обновление проггрессбара по QueudConnection.

"убийственная блокировка" от Qt::QueuedBlockedConnection будет в том, что внутренний поток остановится, пока гуй не доберется до очереди сообщений и не вызовет слот. Это чревато банальным пропуском записываемых данных.
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #13 : Сентябрь 03, 2011, 13:46 »

"убийственная блокировка" от Qt::QueuedBlockedConnection будет в том, что внутренний поток остановится, пока гуй не доберется до очереди сообщений и не вызовет слот. Это чревато банальным пропуском записываемых данных.
Qt::DirectConnection и длинный код слота также остановят ваш поток.
Записан
Akon
Гость
« Ответ #14 : Сентябрь 03, 2011, 14:13 »

Да, но это локальный участок, и пользователь должен не допускать этого. Ведь только ему известна "тяжесть" обработки. Так все коллбэки и строятся. Если обработка достаточно "тяжела", то пользователь должен вынести ее из слота и сделать асинхронной. Qt::DirectConnection в данном случае своего рода общий знаменатель.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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