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

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

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

Вы, вроде бы, механизм понимаете правильно, но жонглиреуете фактами, как заправский циркач, игнорируя плюсы и выдавая минусы за плюсы другого характера Улыбающийся
Qt::DirectConnection или Qt::QueuedBlockedConnection - в Вашем случае разницы никакой (я намеренно опускаю наличие межпоточной блокировки во втором случае). никакого пропуска данных там нет и не будет. упрощая описанную в третьем посте схему, приходим к тому, что слот Вам вовсе и не нужен - достаточно приватного метода, исполняемого в контексте источника данных. но т.к. у Вас некий "клиентский" обект, то допускаю, что какие-то его члены должны быть потоко-безопасными (а иначе я вообще не вижу смысла в этом объекте). подключая слот через Qt::DirectConnection, Вы усложняете себе жизнь необходимостью скрупулёзно следить за lock-free потокобезопасностью, но получаете возможность использовать некий дефицитный ресурс в качестве буфера данных. независимо от того, "тяжёлая" операция производится в слоте или нет, источник данных (поток) занимается не своей задачей, данные в это время накапливаются в некотором ином буфере, возникает потенциальная задержка, а возможности как-либо контролировать её нет (разве что, "пробрасывать" часть данных - чего Вы, кажется, пытаетесь избежать).
давайте рассмотрим простейшую альтернативу: источник данных имеет пишет в не-такой-дефицитный implicitly shared буфер и выбрасывает queued сигнал со ссылкой на него { QMetaObject::invokeMethod(this, "dataChunkReceived", Qt::QueuedConnection, Q_ARG(QByteArray, &ba)); }, абсолютно не беспокоясь о том, кто и с какими параметрами подключён к сигналу dataChunkReceived(const QByteArray &), после чего сразу же возвращается к своей прямой обязанности - ждать данные и складывать их в буфер. имея пару-тройку буферов в распоряжении, вероятность memory reallocation любого из буферов стремится к нулю. слот, подключённый к вышеобозначенному сигналу, уже в другом контексте выполняет над данными произвольные операции, швыряется произвольными сигналами либо же попросту спит минуту, но следующий кусок данных он таки получит. проблема только в том, что если объект действительно спит минуту, в очереди событий будут накапливаться всё новые и новые данные, что эффективно решает "проброской" данных, которые уже неактуальны. но раз уж у Вас достаточно навыков и времени на поддержание lock free синхронизации между несколькими объектами, то задача обработки данных "в срок" и/или "проброски" неактуальных данных для Вас будет проще пареной репы;) если же "проброска" данных исключена, несложно добавить в источник данных механизм обнаружения неэффективного использования буферов и усыпления потока - будет 1-в-1 то же самое, что у Вас сейчас происходит при вызове слота, подключённого с Qt::DirectConnection.

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

но я не навязываюсь с данной схемой - просто рассмотрел возможные альтернативы Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

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

Как определить - ну а если незатейливо в run клиента запомнить его currentThreadId и проверять на неравенство текущему?
Записан
Akon
Гость
« Ответ #17 : Сентябрь 03, 2011, 23:44 »

но я не навязываюсь с данной схемой - просто рассмотрел возможные альтернативы Улыбающийся

Всегда рад различного рода альтернативам  Улыбающийся Спасибо.

Цитировать
давайте рассмотрим простейшую альтернативу: источник данных имеет пишет в не-такой-дефицитный implicitly shared буфер и выбрасывает queued сигнал со ссылкой на него { QMetaObject::invokeMethod(this, "dataChunkReceived", Qt::QueuedConnection, Q_ARG(QByteArray, &ba)); }, абсолютно не беспокоясь о том, кто и с какими параметрами подключён к сигналу dataChunkReceived(const QByteArray &), после чего сразу же возвращается к своей прямой обязанности - ждать данные и складывать их в буфер. имея пару-тройку буферов в распоряжении, вероятность memory reallocation любого из буферов стремится к нулю

Спору нет - такая схема очень элегантна, когда источнику данных позволительно выделить дополнительную память, и частота такого выделения приемлемо низка. Схему можно еще немного оптимизировать, если под чанки использовать implicitly shared но без copy on write (т.е. просто allocate on write).

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

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

Если блокировка будет на время, не меньшее времени заполнения остатка буфера, то будет потеря данных на уровне взаимодействия источника данных со звуковухой (запрос на очередной чанк не будет выдан вовремя). На участке источник данных - клиент (что, по всей видимости, вы имели ввиду) потерь данных нет.

Цитировать
Как определить - ну а если незатейливо в run клиента запомнить его currentThreadId и проверять на неравенство текущему?

Да, и так вот незатейливо Улыбающийся неравенство будет означать, что слот вызван из другой нитки, т.к. с QueuedConnection он может быть вызван только из своей!
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


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


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

Да, но это локальный участок, и пользователь должен не допускать этого. Ведь только ему известна "тяжесть" обработки. Так все коллбэки и строятся. Если обработка достаточно "тяжела", то пользователь должен вынести ее из слота и сделать асинхронной. Qt::DirectConnection в данном случае своего рода общий знаменатель.
Странно расчитывать, на то, что с тяжестью обработки пользователь сам разберётся, а с нужным типом коннекта - нет.
Записан
Akon
Гость
« Ответ #19 : Сентябрь 04, 2011, 08:20 »

Пользователь и не разбирается с типом коннекта - ему предлагается только DirectConnect. У себя в слоте, если необходимо, далее делается QueuedConnect.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Пусть даже простейший вариант, без всяких оптимизаций/заморочек: клиент просто принимает все запросы. Почему сервер должен знать как толкнуть клиента. с каких мутексов его снять и.т.п? Более чисто смотрится "сервер уведомляет", а уж клиент разбирается как запуститься. И уведомление должно выполняться в нитке сервера (нитка клиента остановлена)

Да, и так вот незатейливо Улыбающийся неравенство будет означать, что слот вызван из другой нитки, т.к. с QueuedConnection он может быть вызван только из своей!
Ну да, а разве Вам не это надо?
Записан
Akon
Гость
« Ответ #21 : Сентябрь 04, 2011, 10:15 »

Ну да, а разве Вам не это надо?

Да, применительно к описанной мною задаче это должно работать, спасибо!

Изначальный вопрос ("Как проверить, что для данной пары сигнал/слот установлено Qt::DirectConnection?") трактуется несколько шире - источник данных может выдавать данные и в контексте потока клиента. 
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


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