Название: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: IGHOR от Июль 20, 2012, 01:48 Есть главный класс наследник QObject в котором есть слот someSlot() и сигнал initSomeSlot() который тоже в этом объекте.
Есть множество запущенных QThread наследников и у каждого из них есть указатель на главный QObject. Безопасно (thread safe) ли вызывать внутри QThread по указателю метод из основного QObject который инициализирует сигнал initSomeSlot()? Делается это чтобы не тормозить поток в главном QObject и чтобы не делать кучу connect для каждого QThread. Название: Re: Безопасно ли так делать? Отправлено: Bepec от Июль 20, 2012, 06:48 Т.е. у тебя вызывается слот основного потока из других потоков?
А что этот слот делает? Название: Re: Безопасно ли так делать? Отправлено: sidsukana от Июль 20, 2012, 07:28 А мутексы уже не в моде? Ну или на крайняк "метод основного объекта" сделать слотом и соединить его с сигналом из потока по связи BlockedConnection.
Название: Re: Безопасно ли так делать? Отправлено: Bepec от Июль 20, 2012, 07:31 Блокед коннекшен убьёт гуи.
Тут же какая то кривая реализация проскакивает :D PS совет - используйте сигнал-слоты. Не мешайте чёрное с горячим, жёсткое с дешёвым, вызов сигнал слота прямым вызовом и коннект сигнала :D Название: Re: Безопасно ли так делать? Отправлено: Igors от Июль 20, 2012, 11:51 Безопасно (thread safe) ли вызывать внутри QThread по указателю метод из основного QObject который инициализирует сигнал initSomeSlot()? То "инициализирует" - большая мутность. Наверное эмиттит, испускает сигнал. Если код слота thread-safe то да. Если нет - использовать QueuedConnection (при этом однако слот сработает позже что может не устроить)Название: Re: Безопасно ли так делать? Отправлено: IGHOR от Июль 20, 2012, 22:50 Попробую объяснить подробнее..
Есть несколько тредов, 8 например. И динамически создаются объекты наследники QObject при этом каждый перемещается в один из тредов и никогда не удаляется. Каждый объект должен посылать данные QByteArray в "главный" поток. Хочу избежать создания множества пар сигнал слотов при добавлении нового объекта в тред. Это не критично но упростит понимание и является оптимизацией (или нет?). Значит: 1) у каждого объекта есть указатель на "главный" 2) в "главном" объекте есть метод (не слот) в котором инициируется сигнал соединенный с слотом "главного" объекта. Сигнал инициируется в треде и так думаю в результате должен запустится слот в "главном" объекте, будет ли это threadsafe? Название: Re: QThread. Безопасно ли так делать? Отправлено: kostya2vntu от Июль 21, 2012, 01:38 Код в студию ;)
Название: Re: QThread. Безопасно ли так делать? Отправлено: IGHOR от Июль 21, 2012, 03:31 Подумал и обобщил вопрос.
Есть два треда ThreadA и ThreadB. У первого есть указатель на второй. Надо передавать данные из А в В без сигналов слотов между ThreadA и ThreadB так чтобы это было ThreadSafe и не тормозило треды. И да, код слота slotSendData есть ThreadSafe и он обрабатывает данные и может отправить их в другой тред. Прилагаю файлы с примером как я это сделал. Есть множество тредов (или объектов в разных тредах) между которыми надо передавать данные в QByteArray. Я сделал так что каждый объект сбрасывает данные в главный тред и там определяется куда его отправить дальше (в другой тред). Думаю нельзя соединить много объектов сигналами во всех комбинациях поэтому так делаю. Алгоритм кратко: 1) ThreadA по указателю вызывает функцию functionSendData из ThreadB 2) в функции functionSendData вызывается сигнал signalSendData который соединен со слотом в этом же ThreadB 3) обрабатывается слот slotSendData изпод ThreadB Выходит ThreadA по сигналу запускает слот в ThreadB и при этом нет явного соединения ThreadA<=>ThreadB и любой тред может обратится к другому без предварительного connect к нему. Скажите оптимально ли это реализовано? main.cpp Код: #include <QtGui/QApplication> threada.h Код: #ifndef THREADA_H threada.cpp Код: #include "threada.h" threadb.h Код: #ifndef THREADB_H threadb.cpp Код: #include "threadb.h" Вывод Debug Код: Main Thread ID: 0x1af4 Название: Re: Безопасно ли так делать? Отправлено: Igors от Июль 21, 2012, 10:44 Это может быть thread-safe или нет в зависимости от содержания ThreadB::functionSendData. Вот пример когда нет
Код При вызове этого метода напрямую он выполняется в той же нитке что и вызывающий. Если 2 или более нитки одновременно выполняют код выше - рухнет т.к. += контейнера не thread-safe. Если же защитить такие места мутексами - все норм Название: Re: QThread. Безопасно ли так делать? Отправлено: IGHOR от Июль 21, 2012, 11:06 Это может быть thread-safe или нет в зависимости от содержания ThreadB::functionSendData. Вот пример когда нет Функция functionSendData создана только для того чтобы запустить сигнал с данными. Там будет только одна строчка как в примере. А обработка данных только в slotSendData. Это разве не ThreadSafe? Название: Re: QThread. Безопасно ли так делать? Отправлено: Igors от Июль 21, 2012, 11:19 Функция functionSendData создана только для того чтобы запустить сигнал с данными. В Вашем коде этот сигнал вызывается через EventLoop (сработает QueuedConnection), поэтому эффект/оптимизация те же самые как если бы ThreadA испустила сигнал. А если использовать DirectConnection, то с thread-safe все то жеТам будет только одна строчка как в примере. А обработка данных только в slotSendData. Это разве не ThreadSafe? Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: IGHOR от Июль 21, 2012, 11:38 эффект/оптимизация те же самые как если бы ThreadA испустила сигнал. По поводу оптимизации тоже думаю что нет разницы.В итоге получилась конструкция (new QThread)->sendData(..) которая вызывает сигнал по функции из другого треда. И у каждого QThread есть указатель на главный QThread, данные передаются в последний этим методом а потом определяется в который QThread отправить их дальше, и тоже по указателю так делается. В результате сигнал со слотом соединены только внутри каждого объекта самому к себе и нет надобности соединять сигнал со слотом всех остальных тредов. А как бы вы реализовали передачу данных между 1000 штук QThread (или просто QObject)? Разве удобно создавать между всеми ими связь? Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: Igors от Июль 21, 2012, 11:50 В результате сигнал со слотом соединены только внутри каждого объекта самому к себе и нет надобности соединять сигнал со слотом всех остальных тредов. Ничего плохого в этом нет, если Вам так удобнее - ну и делайте. Также эта конструкция может иметь смысл чтобы определить thread-источник по ее IDА как бы вы реализовали передачу данных между 1000 штук QThread (или просто QObject)? Это столь же удобно как и хранить 100 штук указателей на "основную" нитку. Но Вы же эти 100 указателей как-то записали :)Разве удобно создавать между всеми ими связь? Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: Bepec от Июль 21, 2012, 12:49 Как говорил один человек - если в программе больше 20 потоков - это плохая программа :D
Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: Igors от Июль 21, 2012, 13:04 Как говорил один человек - если в программе больше 20 потоков - это плохая программа :D То когда было. А сейчас меньше 8 ядер - бедновато, а 16-ю никого не удивишьНазвание: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: IGHOR от Июль 21, 2012, 15:11 Как говорил один человек - если в программе больше 20 потоков - это плохая программа :D Да это правда, но в проге есть число потоков только в двое больше чем количество ядер.И данные будут передаваться от объекта к объекту которые принадлижат разным тредам. Суть дела не меняется. Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: Bepec от Июль 21, 2012, 16:37 :P
Непонятна твоя задача :) Без сигнал слотов хотел бы сделать - я б понял, они медленные. Но ты их используешь. С сигнал слотами сделал бы - я б понял, ибо сигнал слотовое заточено на межпотоковое соединение. Но ты зачем то отказываешься от них. Функции, вызываемые с потоком должны быть потокобезопасными - с использованием мутексов и семафоров. Этого у вас пока нет. PS я пока вашу архитектуру не представляю. Не умещается в моей голове, скажем так - извращённое использование/неисползование сигнал-слотов :) Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: Igors от Июль 21, 2012, 17:23 Ладно уж, пофлудим (в меру)
Функции, вызываемые с потоком должны быть потокобезопасными - с использованием мутексов и семафоров. Этого у вас пока нет. Не устаю удивляться насколько точен расчет Qt! Предоставляемые ими средства multi-thrеadng, мягко говоря, "весьма затратны", а по-простому - слабы. Но зато как удобно пулять сигналами из нитки в нитку. И вот уже (робкий) малюсенький шажок в сторону квалифицируется как несомненное извращение :) Хотя человек и не думал покушаться на святую корову - сигналы! PS я пока вашу архитектуру не представляю. Не умещается в моей голове, скажем так - извращённое использование/неисползование сигнал-слотов :) Ну и вообще-то чем меньше мутексов - тем лучше, в этом и состоит искусство multi-theadng Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: Bepec от Июль 21, 2012, 20:00 Igors опять разведём баталию? :D
Тут человек использует Оо вызов функции, которая в свою очередь вызывает сигнал Оо. Я тут не вижу явных преимуществ перед просто сигналом :) Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: IGHOR от Июль 21, 2012, 23:08 Я тут не вижу явных преимуществ перед просто сигналом :) Представьте что у вас есть 10000 объектов разбросанных в разных тредах. Вам надо передать данные из одного то в другой само собой методом сигнал слота чтобы не тормозить треды. Как вы бы это реализовали?
Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: mutineer от Июль 21, 2012, 23:13 Предлагать среди вариантов метод, который непонятен отвечающему - это пять:)
Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: IGHOR от Июль 22, 2012, 03:16 Предлагать среди вариантов метод, который непонятен отвечающему - это пять:) Вопрос скорее к всем.Но отвечающий пусть тоже свою версию оптимальной реализации скажет :) Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: Igors от Июль 22, 2012, 03:33 Представьте что у вас есть 10000 объектов разбросанных в разных тредах. Напр такВам надо передать данные из одного то в другой само собой методом сигнал слота чтобы не тормозить треды. Как вы бы это реализовали? Код Другое дело что обмен через очередь далеко не всегда лучшее решение. Если операции секунда и больше - все отлично, Но частенько бывает что время операции намного меньше постановки в очередь + извлечения из нее. Тогда тормоза и бестолковое сжигание процессорного времени. Вот с этой точки зрения Ваша схемка имеет смысл. Можно свести к обычной очереди (как сейчас), можно обработать в вызывающей нитке, можно комбинировать так и сяк. При этом решения можно сосредоточить в классе ThreadB Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: Bepec от Июль 22, 2012, 10:22 Самое простое решение - поток менеджер, имеющий указатели на все потоки, принимающий сигнал с 2 параметрами - номер потока куда передать и данные. Всё.
Так же вообще можно без сигналов - опять же поток менеджер с thread-safe функцией добавления/передаич данных из своей очереди :D Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: IGHOR от Июль 22, 2012, 13:17 Самое простое решение - поток менеджер, имеющий указатели на все потоки, принимающий сигнал с 2 параметрами - номер потока куда передать и данные. Всё. Да у меня в основном потоке есть указатели на все потоки. Если соединять Тред=>Главный сигнал слотом то данные передадутся. Но надо их еще обратно передавать в другой тред и чтобы обойтись без мютексов придется еще делать соединение Главный=>Тред чтобы послать данные в другой тред. В итоге будет соединений в двое больше чем тредов. В моем методе есть только одно соединение внутри треда, и одно внутри главного потока. Выходит если по моему тогда получится соединений столько же сколько тредов + еще одно в главном потоке. Получается что так делать оптимизированнее. Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: Bepec от Июль 22, 2012, 13:59 Не буду спорить далее - то ли ты меня не читаешь, то ли читаешь не до конца, то ли мы разные.
Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: Igors от Июль 22, 2012, 17:04 В моем методе есть только одно соединение внутри треда, и одно внутри главного потока. Ну это вряд ли. Число вызовов слотов одно и то же, и скорость одна и та же. Меньше число установленных коннектов, но непонятно чего Вы так боитесь - ну создали нужный коннект хоть в конструкторе - и все. Выходит если по моему тогда получится соединений столько же сколько тредов + еще одно в главном потоке. Получается что так делать оптимизированнее. Название: Re: Передача данных между QThread без сигнал-слотов. Безопасно ли так делать? Отправлено: IGHOR от Июль 25, 2012, 21:02 Боялся что могут быть глюки. Но все работает.
В общем зациклился на оптимизации :) Думаю действительно нет разницы. Всем спасибо за общение :) Иду программировать дальше.. |