Russian Qt Forum

Qt => Общие вопросы => Тема начата: vunder от Июнь 24, 2010, 11:01



Название: Потоки (QThread) и сигналы
Отправлено: vunder от Июнь 24, 2010, 11:01
Есть приложение с потоком. Поток предназначен для работы с сетью и при получении данных высылает сигналы с результатами. В качестве результатов выступают классы. Как лучше их передавать, чтобы не было утечки памяти?


Название: Re: Потоки (QThread) и сигналы
Отправлено: kibsoft от Июнь 24, 2010, 11:11
Цитировать
В качестве результатов выступают классы
Не путай объекты и классы.
Цитировать
Как лучше их передавать, чтобы не было утечки памяти?
Передавать указатели и удалять в нужный момент (delete). Надо смотреть код, чтобы понять что тебе нужно.


Название: Re: Потоки (QThread) и сигналы
Отправлено: vunder от Июнь 24, 2010, 12:14
А что на счет передачи объектов по ссылке?
Код
C++ (Qt)
void MainWindow::onSpectrumResult(const ResultItem &result)


Название: Re: Потоки (QThread) и сигналы
Отправлено: kibsoft от Июнь 24, 2010, 12:45
Можно и так. Не пойму о какой утечке памяти идет речь. Если объект создается(в стеке например, не через new) в функции принятия данных, то проблем вообще никаких. Ты передаешь ссылку, сигнал отработает и вернет управление в функцию, в конце которой твои объекты сами удалятся. Так что никаких утечек не будет.


Название: Re: Потоки (QThread) и сигналы
Отправлено: vunder от Июнь 24, 2010, 15:09
Можно и так. Не пойму о какой утечке памяти идет речь. Если объект создается(в стеке например, не через new) в функции принятия данных, то проблем вообще никаких. Ты передаешь ссылку, сигнал отработает и вернет управление в функцию, в конце которой твои объекты сами удалятся. Так что никаких утечек не будет.
Это в случае прямого вызова функций. У меня это сигналы, причем в разных потоках. В параметрах connect стои тип соединения auto. Насколько я помню, в этом случае, если получатель и отправитель в разных потоках, то вызов ставиться в очередь (или что-то подобное). Что-то я не уверен, что вызов отправителя при этом блокируется


Название: Re: Потоки (QThread) и сигналы
Отправлено: Amigo_sa от Июнь 24, 2010, 17:10
А что на счет передачи объектов по ссылке?
Код
C++ (Qt)
void MainWindow::onSpectrumResult(const ResultItem &result)

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


Название: Re: Потоки (QThread) и сигналы
Отправлено: explosionhead от Июнь 24, 2010, 18:02
А что на счет передачи объектов по ссылке?
Код
C++ (Qt)
void MainWindow::onSpectrumResult(const ResultItem &result)

Нужно иметь в виду что для сигналов-слотов параметры копируются, это во-первых, лишний вызов копирующего конструктора для ResultItem, а во-вторых, если исходный item поменяется, слот об этом ничего не узнает.
параметры-ссылки не копируются. Но в данном случае тип соединения QueuedConnection и ссылки передавать нельзя
Используй умный указатель, например std::auto_ptr


Название: Re: Потоки (QThread) и сигналы
Отправлено: Igors от Июнь 24, 2010, 19:41
параметры-ссылки не копируются. Но в данном случае тип соединения QueuedConnection и ссылки передавать нельзя
Используй умный указатель, например std::auto_ptr
С точностью до наоборот  :) Для QueuedConnection - ссылки как раз копируются. в остальном QueuedConnection - это как PostMessage в Вындоуз. Привлекать auto_ptr не имеет смысла, т.к. он создается в контексте сигнала и может грохнуть данные в неподходящий момент.

В параметрах connect стои тип соединения auto. Насколько я помню, в этом случае, если получатель и отправитель в разных потоках, то вызов ставиться в очередь
Если получатель и отправитель были СОЗДАНЫ в разных потоках, это важно.

(или что-то подобное). Что-то я не уверен...
Возникает впечатление что Вас заставляют заниматься программированием. Может лучше переключиться на живопись или музыку, где интуитивная компонента больше?  :)


Название: Re: Потоки (QThread) и сигналы
Отправлено: explosionhead от Июнь 24, 2010, 20:29
да, действительно я ошибался относительно QueuedConnection - он скопирует данные. Тогда нечего волноваться относительно вызова копирующего конструктора - он будет вызван в любом случае при этом виде соединений.
Хотя если автор уточнит постановку задачи, то ситуация прояснится. Возможно устроит и обычный DirectConnection


Название: Re: Потоки (QThread) и сигналы
Отправлено: vunder от Июнь 25, 2010, 08:09
Итак, как я понял лучше передавать ссылку на объект, избегая тем самым дополнительный вызов конструктора, а в слоте необходимо будет вызвать delete <object>?


Название: Re: Потоки (QThread) и сигналы
Отправлено: galilley от Июнь 25, 2010, 09:26
А какой объект-то хоть передаётся, и чем плох вызов копирующего конструктора.
Я у себя через сигналами кидаюсь объектами, меньше возни с delete <object> и об утечках не надо заботиться, однако тут надо смотреть на объём этих самих данных и частоту сигналов.


Название: Re: Потоки (QThread) и сигналы
Отправлено: vunder от Июнь 25, 2010, 09:35
А какой объект-то хоть передаётся, и чем плох вызов копирующего конструктора.
Я у себя через сигналами кидаюсь объектами, меньше возни с delete <object> и об утечках не надо заботиться, однако тут надо смотреть на объём этих самих данных и частоту сигналов.

Код
C++ (Qt)
class SpectrumResultItem: public CustomResultItem
{
public:
   SpectrumResultItem();
   QList<float> floatSpectrum;
   QList<float> floatPhases;
   SpcKind kind;
   void setSpectrumData(const QString &strKind, QByteArray &data);
};
 
Отсчетов может быть до 300 (на оба поля floatSpectrum и floatPhases), т.е. до 1200 байт. Но это максимум. Обычно 150, т.е. 600 байт.
Данные будут приходить около 3-4 раз в секунду. Да и то это не постоянный режим работы. Это может длится несколько минут (а то и несколько секунд)


Название: Re: Потоки (QThread) и сигналы
Отправлено: explosionhead от Июнь 25, 2010, 10:39
по идее если ты не будешь изменять содержимое контейнеров floatSpectrum и floatPhases, то оно не будет копироваться
да, кстати, а чем оправдано использование QList<T>? для твоей задачи правильнее использовать QVector<T>


Название: Re: Потоки (QThread) и сигналы
Отправлено: vunder от Июнь 25, 2010, 10:42
по идее если ты не будешь изменять содержимое контейнеров floatSpectrum и floatPhases, то оно не будет копироваться
да, кстати, а чем оправдано использование QList<T>? для твоей задачи правильнее использовать QVector<T>
Да, действительно. Я как-то забыл про него


Название: Re: Потоки (QThread) и сигналы
Отправлено: Igors от Июнь 25, 2010, 10:45
Я бы смотрел самый простой вариант: передать нитке указатели на контейнеры (QList) и пусть нитка их заполняет. А главная отвечает за создание контейнеров, их зачистку и.т.п. Нет проблем с копированием и конструкторами. А можно и не передавать в сигнале, а сделать указатели членами класса нитки.


Название: Re: Потоки (QThread) и сигналы
Отправлено: vunder от Июнь 25, 2010, 10:52
Я бы смотрел самый простой вариант: передать нитке указатели на контейнеры (QList) и пусть нитка их заполняет. А главная отвечает за создание контейнеров, их зачистку и.т.п. Нет проблем с копированием и конструкторами. А можно и не передавать в сигнале, а сделать указатели членами класса нитки.
Да, это мысль. Возможно идеальный вариант для меня. По сути нитей всего 2: основная (GUI) и дополнительная (чтение данных из TCP). Указатели можно передать в конструкторе или через сеттеры, и отправлять сигналы при появлении новых данных. Но тогда нужно добавлять критическую секцию на чтение/запись данных


Название: Re: Потоки (QThread) и сигналы
Отправлено: explosionhead от Июнь 25, 2010, 10:59
вместо критической секции рекомендую использовать QReadWriteLock. читать одновременно могут многие, а писать только один


Название: Re: Потоки (QThread) и сигналы
Отправлено: Igors от Июнь 25, 2010, 23:29
Но тогда нужно добавлять критическую секцию на чтение/запись данных
Это так или иначе неизбежно при работе с 2 или более нитками. Но если использовать QList то все просто - ведь данные размером > 4(8 ) байт не перемещаются в памяти.

Код
C++ (Qt)
static QMutex theMutex;
 
// для обработчика используем GetListSize (вместо theList.size())
int GetListSize( MyList & lst)
{
QMutexLocker lock(&theMutex);
return lst.size();
}
 
// защищаем добавление
void Add2List( MyList & lst, const MyObj & obj )
{
QMutexLocker lock(&theMutex);
lst.push_back(obj);
}
 
// обработчик
...
int i, limit = GetListSize(lst);
for (i = 0; i < limit; ++i) {
// обработка элемента
}
 


Название: Re: Потоки (QThread) и сигналы
Отправлено: SABROG от Июнь 26, 2010, 12:17
вместо критической секции рекомендую использовать QReadWriteLock. читать одновременно могут многие, а писать только один

Лучше сразу изучать lock-free алгоритмы на атомарных операциях, чтобы потом небыло претензий по поводу падения скорости из-за мутексов и т.п.