Название: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 13, 2010, 15:48
У вас есть класс-компонента которая рассчитывает по запросу какие-то значения, а есть классы которым необходимы данные параметры. При этом ни первые ни вторые не желают ничего знать друг о друге. Сигнал-слоты с дополнительным объектом в сигнатуре сигнала помогут связать такие объекты. В каком-то смысле, это "внутрипрограммная" реализация идей SOA - "через сигнал-слот вызывается расчет каких-либо значений, и ни источник ни приемник не знают друг о друге ничего". применение и описание - см в коде. PS: Все вроде потоко-безопасно и подходит для межпоточного взаимодействия, но, признаться пока специально не проверял )))) PS: В качестве бонуса - "кроссплатформенный Sleep" - static void SleepMS_qt( unsigned int time) ------------------------------------------------ Исходный код класса: t_returnSyncObject.h Код: /* t_returnSyncObject.cpp Код: /* ------------------------------------------------ Исходный код приложения: код вызывающей стороны, у вызывающей стороны есть сигнал void mySignal(t_returnSyncObject *syncResultObject) который подключен к слоту, который описан в последнем листинге. Код: t_returnSyncObject *syncResultObject=new t_returnSyncObject(this); код слота: Код: void myClass2::mySlot(t_returnSyncObject *syncResultObject) Обсуждаем, комментируем, в меру ругаем, улучшаем ? :) PS: из улучшений я пока могу предложить только добавить обработку сообщений в цикле ожидания (bool t_returnSyncObject::waitForDone(int _timeOut)) - что бы не "замирать" в случае чего... PS: также можно попытаться развить возврат множества значений в класс-источни-сигнала. Но это на личное усмотрение) Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Akon от Октябрь 13, 2010, 19:08 похоже на visitor.
методы isDone() и result() должны быть const. поле _done должно быть volatile. waitForDone() в общем случае должен принимать callback - пользователь твоего класса сам решит чем нагрузить. обработка цикла сообщений это частный случай. Ну и стиля Qt лучше придерживаться, имхо. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 13, 2010, 22:20 2 Akon : ээээ.... вы кажется не поняли зачем нужен класс или как я его применяю.
методы isDone() и result() должны быть const. эти методы нужны для возврата данных именно в тот экземпляр объекта который испустил слот, именно в то место и время, где он был испущен. И относятся они именно к тому экземпляру t_returnSyncObject, ссылка на который нам прислана с сигналом.Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: spectre71 от Октябрь 13, 2010, 22:47
1) Например Qt::DirectConnection, или выставить флаг, или послать обратный сигнал, или ... 2) Например Qt::DirectConnection, или выставить флаг, или послать обратный сигнал, или ... 3) поскольку ты где-то делаешь прямое подключение, легко сделать там и обратное подключение - самое примтивное. Или ... 4) Интерфейсы, менеджеры интерфейсов и прочая паттерная хрень :) Или ... Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 14, 2010, 00:10 1) Например Qt::DirectConnection, или выставить флаг, или послать обратный сигнал, или ... Qt::DirectConnection при межпотоковом взаимодействии всегда(!) становится Qt::QuotedConnection; 2) Например Qt::DirectConnection, или выставить флаг, или послать обратный сигнал, или ... 3) поскольку ты где-то делаешь прямое подключение, легко сделать там и обратное подключение - самое примтивное. Или ... 4) Интерфейсы, менеджеры интерфейсов и прочая паттерная хрень :) Или ... выставлять флаг? где? и куда смотреть? связанные объекты даже ссылок не имеют друг на друга....; обратное подключение?! и что? отправив сигнал-запрос, я должен ловить результат в другом слоте, а в итоге - "одну простую функцию" разносить на несколько слотов и фактически - "делать громоздкую реализацию машины состояний" вместо одного простого линейного алгоритма который должен запросить несколько фнешних параметров?? не-не-нееее) "Интерфейсы, менеджеры интерфейсов и прочая паттерная хрень"? дада) именно хрень. тем более в условиях когда сигнатура функции фактически и является описанием мини-интерфейса. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Kolobok от Октябрь 14, 2010, 00:29 Qt::DirectConnection при межпотоковом взаимодействии всегда(!) становится Qt::QuotedConnection; В этом случае можно использовать Qt::BlockingQueuedConnection. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: voral от Октябрь 14, 2010, 00:31 Хм.. Может у меня такой особой необходимости не возникало идти таким путем....
А почему не через sender()? Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 14, 2010, 00:42 Qt::DirectConnection при межпотоковом взаимодействии всегда(!) становится Qt::QuotedConnection; В этом случае можно использовать Qt::BlockingQueuedConnection. Цитировать This connection type should only be used where the emitter and receiver are in different threads. Note: Violating this rule can cause your application to deadlock. т.е. в таком случае - я должен постоянно следить за тем, что в каком потоке у меня находится и куда я обращаюсь? не хочу. геморно. "тут так напиши, а тут так"...(кстати, спасибо за инфу - не залазил в данную часть ассистанта со времен 4.3 - тогда этого типа соединения не было))) А почему не через sender()? мне не надо обращаться к объекту-источнику. Мне надо вернуть ему результат. Далее - попытка использовать sender() требует от меня знать класс объекта который меня вызывает. и даже не говоря о том, что поэтому sender() "нарушает" "сигнал-слотовую парадигму"(?)(см замечания троллей в ассистанте), - он работает только в рамках соединений типа QT::QuotedConnection - т.е. в рамках одного потока. (или в новых версиях QT уже это поменяли??)))) Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: spectre71 от Октябрь 14, 2010, 01:44 1) Например Qt::DirectConnection, или выставить флаг, или послать обратный сигнал, или ... Qt::DirectConnection при межпотоковом взаимодействии всегда(!) становится Qt::QuotedConnection; 2) Например Qt::DirectConnection, или выставить флаг, или послать обратный сигнал, или ... 3) поскольку ты где-то делаешь прямое подключение, легко сделать там и обратное подключение - самое примтивное. Или ... 4) Интерфейсы, менеджеры интерфейсов и прочая паттерная хрень :) Или ... выставлять флаг? где? и куда смотреть? связанные объекты даже ссылок не имеют друг на друга....; обратное подключение?! и что? отправив сигнал-запрос, я должен ловить результат в другом слоте, а в итоге - "одну простую функцию" разносить на несколько слотов и фактически - "делать громоздкую реализацию машины состояний" вместо одного простого линейного алгоритма который должен запросить несколько фнешних параметров?? не-не-нееее) "Интерфейсы, менеджеры интерфейсов и прочая паттерная хрень"? дада) именно хрень. тем более в условиях когда сигнатура функции фактически и является описанием мини-интерфейса. Я не зря написал везде или ... Вариантов много... Для разных ситуаций - свой. А про "хрень", интерфейсы в большинстве случаев более оптимальное решение для твоего пункта (4). Теперь про это: "обратное подключение?! и что? отправив сигнал-запрос, я должен ловить результат в другом слоте" Ты хочешь всегда! - отправил запрос - ждем результата? А как же асинхронная работа потоков. Используй тогда DirectConnection. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: SASA от Октябрь 14, 2010, 10:21
2. Уже есть - Qt::ConnectionType. 3. Это противоречит идеи сигнал/слот. (но сам грешен, получаю :'() 4. Шаблон - стратегия. Можно продумать идею "Единичный сигнал". Т.е. сигнал соединяется всегда с одним слотом. Т.е. упростить идею до непрямого вызова функции. Это уже есть QMetaObject::invokeMethod. Но нужно знать у кого вызывать, что не всегда удобно. З.Ы. Можно прикрепить архив со всем проектом, что изучать код в любимой IDE. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 14, 2010, 11:51 Используя термины SASA, полагаю можно сказать, что :
... назначение класса t_returnSyncObject - обеспечить механизм непрямого синхронного "потоко-безопасного" вызова функций, через сигнал-слотовый механизм, с возвратом рассчитываемого значения. По сравнению с QMetaObject::invokeMethod, данный механизм лучше тем, что объекту-пользователю нет необходимости знать кто именно обслуживает его обращение. По сравнению различными типами подключения (Qt::DirectConnection/Qt::BlockingQueuedConnection/QT::QuotedConnection) - данный механизм обеспечивает "псевдо-синхронное взаимодейтсвие" не требующее специального типа подключения в зависимости от нахождения объектов в одном или разных потоках. и расскажите подробнеее - почему вы считаете что желание "проверить что твой сигнал получен и обработан?" - это "противоречит идеи сигнал/слот."? разве, скажем TCP противоречит UDP? ))))) Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: navrocky от Октябрь 14, 2010, 12:55 PS: В качестве бонуса - "кроссплатформенный Sleep" - static void SleepMS_qt( unsigned int time) Как вариант могу предложить следующий хак: Код
Кстати для меня загадка, зачем тролли сделали эти методы protected ??? Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 14, 2010, 16:58 PS: В качестве бонуса - "кроссплатформенный Sleep" - static void SleepMS_qt( unsigned int time) Как вариант могу предложить следующий хак:Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: BRE от Октябрь 14, 2010, 17:19 Кстати для меня загадка, зачем тролли сделали эти методы protected ??? Потому что нет никакой необходимости усыплять главный поток.Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: SASA от Октябрь 14, 2010, 17:20 и расскажите подробнеее - почему вы считаете что желание "проверить что твой сигнал получен и обработан?" - это "противоречит идеи сигнал/слот."? разве, скажем TCP противоречит UDP? ))))) Сигнал - это способ сообщить всем, что с объектом что-то случилось. Параметры - подробности случившегося. Этот сигнал могут принять любое (включая ноль) количество заинтересованных. Например. Нажали кнопку "Выход". Кнопки нет дела, до того, что она делает. Но она говорит "Меня нажали". Приложение ловит сигналы от кнопки и отрабатывает реакцию - закрывается. З.Ы. Это в идеале. Но злостные хукеры, типа нас с Вами, используют этот механизм в своих низменных целях ;D З.З.Ы. Пошел учить паттерны. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: SASA от Октябрь 14, 2010, 17:23 Кстати для меня загадка, зачем тролли сделали эти методы protected ??? Потому что нет никакой необходимости усыплять главный поток.И чтоб нельзя было усыпить поток из вне. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 15, 2010, 00:11 Сигнал - это способ сообщить всем, что с объектом что-то случилось. Параметры - подробности случившегося. Этот сигнал могут принять любое (включая ноль) количество заинтересованных. мой класс дает направление уникального нового способа получить сразу кучу разных результатов при попытке обратиться к обшественности.типа "кто тут?" и тебе в ответ хох голосов.. ну класно же) мульти вызов функции))) позволяет например одним сигнлом промониторить состояние десятка обхектов - надо только переписать методо setResult() таким образом что бы он добавлял новое значение в массив. )))) согласитесь - наступать на грабли одновременно и неизвестно с кем - веселее) Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Igors от Октябрь 15, 2010, 01:21 Ладно, поругаем :)
1) Какие преимущества по сравнению с BlockingConnection? Вижу одно: можно отвалиться по таймауту - ну значит на это надо упирать (подчеркивать) в описании ф-циональности. И вопрос: а что делать с эти объектом Код: t_returnSyncObject *syncResultObject=new t_returnSyncObject(this); Цитировать return -1; есть утечка, нужно зачищать с блокировками.2) В каком-то смысле, это "внутрипрограммная" реализация идей SOA - "через сигнал-слот вызывается расчет каких-либо значений, и ни источник ни приемник не знают друг о друге ничего". Ну так уж и ничего? :) Как минимум оба знают t_returnSyncObject. Возможности взаимодействия определяются тем что умеет/понимает этот (интерфейсный) класс. Потребуется больше параметров - и придется доливать т.к. одним QVariant уже не обойтись (ну или раздувать QVariant что по сути то же). Я против этого ничего не имею, но не вижу что тут нового/выгодного.Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: navrocky от Октябрь 15, 2010, 09:45 Кстати для меня загадка, зачем тролли сделали эти методы protected ??? Потому что нет никакой необходимости усыплять главный поток.И чтоб нельзя было усыпить поток из вне. Ну иногда все-таки надо усыплять главный поток, не все же гуёвые приложения.. А во вторых усыпить поток извне этими функциями не возможно. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: BRE от Октябрь 15, 2010, 10:55 Ну иногда все-таки надо усыплять главный поток, не все же гуёвые приложения.. Это для чего например? Что бы приложение выполнялось по дольше?Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: navrocky от Октябрь 15, 2010, 11:03 Ну иногда все-таки надо усыплять главный поток, не все же гуёвые приложения.. Это для чего например? Что бы приложение выполнялось по дольше?Тесты, работа с оборудованием, всякие специфические задачи, типа запустить программку подождать немного, обратиться... Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: BRE от Октябрь 15, 2010, 11:10 Тесты, работа с оборудованием, всякие специфические задачи, типа запустить программку подождать немного, обратиться... Ну как бы подобные вещи принято делать в отдельных потоках и пусть они там себе ждут, если надо.А вот для чего останавливать главный поток? Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: SASA от Октябрь 15, 2010, 12:59 Тесты, работа с оборудованием, всякие специфические задачи, типа запустить программку подождать немного, обратиться... Тролтех подумал об этом void QTest::qSleep ( int ms ) ;DНазвание: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Igors от Октябрь 15, 2010, 17:28 А вот для чего останавливать главный поток? Да его только и делают что усыпляют :) Чем занимается главная нитка - ждет событий (на том же мутексе/семафоре), то же "усыпление".Что касается sleep (в любой форме), то сколько раз я его ставил - столько же и убирал. Упирается в то что глупо ждать когда ответ уже есть. Так что sleep - для тестовых/отладочных целей, не более. Другое дело - напр ждать на семафоре заданное время, такая возможность есть. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 15, 2010, 17:44 Что касается sleep (в любой форме), то сколько раз я его ставил - столько же и убирал. Упирается в то что глупо ждать когда ответ уже есть. Так что sleep - для тестовых/отладочных целей, не более. Другое дело - напр ждать на семафоре заданное время, такая возможность есть. Sleep удобен когда работаешь с оборуоваием и реализуешь в одной процедуре некий протокол обмена данными.Мол авторизация, 5 сек ждем ответа, команда, ждем ответа, выключиться, ждем статуса завершения. Если описанное выше делать в асинхронной сигнал слотовой модели - мне нужно делать машину состояний с 4 состояниями, писать 3 процедуры и кучу проверок. И городить ещё и таймер , что бы отслеживать таймаут. Со слипом это прекрасно уложится в одну функцию. Короткую, простую, понятную. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: navrocky от Октябрь 15, 2010, 18:09 Цитировать Со слипом это прекрасно уложится в одну функцию. Короткую, простую, понятную. Плюсую. Что бы тут не говорили иногда sleep нужен, и тролли лучше бы сделали одну нормальную реализацию, чем плодили бы их в каждом модуле отдельно.. ну бог им судья. Я лично пользую sleep из буста... Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: BRE от Октябрь 15, 2010, 19:04 Да его только и делают что усыпляют :) Чем занимается главная нитка - ждет событий (на том же мутексе/семафоре), то же "усыпление". Мы говорим конкретно про sleep в главном потоке, судя по следующему тексту ты это понял, для чего это "пояснение" про мютексы/семафоры? Или это не мне "пояснение" или ты думаешь я этого не знаю?Упирается в то что глупо ждать когда ответ уже есть. Золотые слова.Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: BRE от Октябрь 15, 2010, 19:06 Мол авторизация, 5 сек ждем ответа, команда, ждем ответа, выключиться, ждем статуса завершения. Для чего это делать в главном потоке? Запусти нитку и пусть она хоть по десять минут ждет ответа.Если описанное выше делать в асинхронной сигнал слотовой модели - мне нужно делать машину состояний с 4 состояниями, писать 3 процедуры и кучу проверок. И городить ещё и таймер , что бы отслеживать таймаут. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Igors от Октябрь 15, 2010, 19:18 Если не надо отслеживать cancel и перерисовывать окна (а за 5 сек это может понадобиться) - ну тогда конечно sleep всем хорош :) Ну да бог с ним, мы отвлеклись.
А вот как удалять созданный экземпляр t_returnSyncObject ? Я поприкидывал, но не вижу простого решения - сложновато получается. Какие есть мнения? Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 15, 2010, 19:54 Для чего это делать в главном потоке? Запусти нитку и пусть она хоть по десять минут ждет ответа. А,... ну если так... )) но тут скорее вопрос не в главном потоке или нет, а в том, что как "заснуть" в методе класса?т.е. у меня есть класс - я его засунул в параллельный поток. Потом срабатывает слот - и в этом слоте(слоту?)) мне надо сделать "описанный выше протокол". Я могу получить поток, в котором я сейчас нахожусь - но мне это ничего не даст. т.к. метод "поспать" у обычного QT-шного потока - частный. Приходится или извращаться, или делать кроссплатформенную обертку над ос-зависимыми функциями. Вспомните - с чего данная нить разговора началась?) Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 15, 2010, 19:59 А вот как удалять созданный экземпляр t_returnSyncObject ? ... Какие есть мнения? сам удалится сборщиком мусора) почему не?или с сигналом пересылать QPointer<returnSyncObject> для безопасности, а в конструкторе returnSyncObject сделать deleterLater? все равно объекту не нужно жить дольше чем работает функция в которой он создан. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: BRE от Октябрь 15, 2010, 20:05 Вспомните - с чего данная нить разговора началась?) Я помню. :)Если твой класс является наследником от QThread, то sleep будет доступен для всех его методов. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Igors от Октябрь 15, 2010, 20:15 или с сигналом пересылать QPointer<returnSyncObject> для безопасности, а в конструкторе returnSyncObject сделать deleterLater? Не дождались ответа - кончился таймаут. Удалили объект и вышли. Слот проснулся, долбит удаленный объект. Ваши действия?все равно объекту не нужно жить дольше чем работает функция в которой он создан. Edit: еще одно соображение: если вышли по таймауту, то по-хорошему слот не должен выполнять действий, т.к. поезд ушел. Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 15, 2010, 20:26 Не дождались ответа - кончился таймаут. Удалили объект и вышли. Слот проснулся, долбит удаленный объект. Ваши действия? эээээ.... "слот проснулся" - т.е. наконец до него был доставлен сигнал? приемный класс никого не "долбит". Если Pointer<returnSyncObject> выдал что объект удален - то извините. Поздно. Никаких действий. Это если с QPointer. Если с простыми ссылками - то объект не должен быть удален пока на него есть ссылки. И собственно приемный объект. А собственно какие проблемы если ничго не делать? Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: ритт от Октябрь 15, 2010, 20:34 я вот читаю-читаю и никак понять не могу - чем вам invokeMethod() не угодил?
результаты возвращать позволяет, прямые и отложенные (в т.ч. и с блокировкой) вызовы поддерживает, никаких хитрых объектов городить и портить сигнатуры не нужно... Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Igors от Октябрь 15, 2010, 21:04 "слот проснулся" - т.е. наконец до него был доставлен сигнал? ДаА собственно какие проблемы если ничго не делать? Если объект не удалять - течет память. Если удалять - обработчик получает невалидный указатель.приемный класс никого не "долбит". Если Pointer<returnSyncObject> выдал что объект удален - то извините. Поздно. Никаких действий. А когда выдал? Слот получает сигнал и начинает его обрабатывать. В этот момент у посылающего кончился таймаут - и объект удален. Тогда получается нужен QSharedPointer, хотя лучше держать информацию об отмене в самом объекте.Это если с QPointer. Если с простыми ссылками - то объект не должен быть удален пока на него есть ссылки. И собственно приемный объект. Это понятно но Вы уж пожалуйста оформите все как положено, ведь это "кладовая готовых решений". Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: Denjs от Октябрь 15, 2010, 21:16 я вот читаю-читаю и никак понять не могу - чем вам invokeMethod() не угодил? он требует знания о том, то тебя вызвал и его методах. результаты возвращать позволяет, прямые и отложенные (в т.ч. и с блокировкой) вызовы поддерживает, никаких хитрых объектов городить и портить сигнатуры не нужно... Т.е. вы не "портите сигналтуры", - вы "портите методы класса"))) пр сигнал слотовом механизме я даже к наименованию не привязан, не коворя о получении ссылки "на объект на другом конце". Название: Re: Синхронное обращение через сигнал слоты и возврат результата расчета после emit Отправлено: ритт от Октябрь 15, 2010, 22:28 он требует знания о том, то тебя вызвал и его методах. ась? это вообще о чём было? зачем знать апи вызывающего? при чём тут методы класса и их порча?Т.е. вы не "портите сигналтуры", - вы "портите методы класса"))) пр сигнал слотовом механизме я даже к наименованию не привязан, не коворя о получении ссылки "на объект на другом конце". какому-такому наименованию?что за объект на другом конце и зачем нужна ссылка на него? если это про объект, испустивший сигнал, то `sender()` в помощь. короче, них не понял я пред.мессага... |