crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> Синхронизация при сигналах и слотах в разных потоках
Алексей1153
  опции профиля:
сообщение 22.1.2013, 12:59
Сообщение #1


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  



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

Понимаю, что глупый вопрос, поэтому задам его по-другому: в каких случаях при использовании сигнала в одном потоке и слота в другом требуется синхронизация ?

Ситуация простейшая - передаю, к примеру, QString по значению из потока в поток

Сообщение отредактировал Алексей1153 - 23.1.2013, 8:23
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 23.1.2013, 3:46
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


если по значению, то передаваемая величина просто копируется.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 23.1.2013, 8:24
Сообщение #3


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


то есть, если в параметрах нет ссылок и указателей (включая и мемберы параметра, если есть) - то про синхронизацию можно не думать ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ssoft
  опции профиля:
сообщение 24.1.2013, 9:01
Сообщение #4


Участник
**

Группа: Участник
Сообщений: 130
Регистрация: 17.2.2010
Из: Москва
Пользователь №: 1470

Спасибо сказали: 30 раз(а)




Репутация:   3  


1. Если передача параметров происходит по значению.

signals:
    void foo ( QString );
    void foofoo ( const & QString );


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

2. Если передача параметров происходит по указателю по не константной ссылке.

signals:
    void foo ( QString * );
    void foo ( QString & );
    void foofoo ( const QString * );


то при асинхронном вызове копируется значение указателя (ссылки), за существование объекта QString и синхронизацию доступа к нему отвечает сам программист.

Сообщение отредактировал ssoft - 24.1.2013, 9:04
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 24.1.2013, 9:12
Сообщение #5


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


ssoft, вот я именно про случай без ссылок. Я в детали механизма сигналов/слотов глубоко не вникал - вероятно они уже имеют свои синхронизаторы для этого случая ? То есть - в некий "почтовый ящик" значение положилось, а потом его адресат (слот) вытащит, и неважно, что это из другого потока произошло

----------------
а со ссылками (неважно, кстати, константные или нет) - ну тут и так понятно, что синхронизировать надо

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
iReset
  опции профиля:
сообщение 24.1.2013, 9:40
Сообщение #6


Участник
**

Группа: Участник
Сообщений: 178
Регистрация: 6.6.2012
Пользователь №: 3414

Спасибо сказали: 23 раз(а)




Репутация:   2  


Цитата(ssoft @ 24.1.2013, 10:01) *
1. Если передача параметров происходит по значению.
...
то при асинхронном вызове (через очередь сообщений), передаваемые данные копируются и синхронизировать ничего не нужно.

А вот для меня этот ответ не совсем полон и остаются вопросы. Поясню:
1. Все функции в классе QString реентерабельны, за исключением некоторых (тут в самом начале). Т.е. при вызове этих функций уже необходимо обеспечивать блокировки. Другие функции, вроде бы, можно использовать в разных потоках, потому что у нас две копии QString.
Но...
2. QString использует неявное разделение данных (тут 4 абзац). Т.е. обе копии QString будут указывать на одни и те же данные до их изменения.

Что будет при одновременном изменении строки в одном потоке и чтении в другом? Вероятно, каша, поскольку для хранения данных в QString используется структура
    struct Data {
        QBasicAtomicInt ref;
        int alloc, size;
        ushort *data;
        ushort clean : 1;
        ushort simpletext : 1;
        ushort righttoleft : 1;
        ushort asciiCache : 1;
        ushort capacity : 1;
        ushort reserved : 11;
        ushort array[1];
    };

и, естественно, она обновится не атомарно.

Все это мои теоретические выкладки, на практике не проверял.

Цитата(Алексей1153 @ 24.1.2013, 10:12) *
...я именно про случай без ссылок. Я в детали механизма сигналов/слотов глубоко не вникал - вероятно они уже имеют свои синхронизаторы для этого случая ? То есть - в некий "почтовый ящик" значение положилось, а потом его адресат (слот) вытащит, и неважно, что это из другого потока произошло

Я думаю, что если в документации (тут, после примера 3 абзац) прямо сказано, что соединяться можно с использованием соединения через очередь, то это работает.

Цитата(Алексей1153 @ 24.1.2013, 10:12) *
а со ссылками (неважно, кстати, константные или нет) - ну тут и так понятно, что синхронизировать надо

Если речь идёт про классы Qt, то не обязательно, если используются только потокобезопасные функции (тут).
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 24.1.2013, 9:57
Сообщение #7


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


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

а вот указатели на локальные данные при Qt::QueuedConnection точно нельзя по определению

так, а это что за комиссия )
Цитата
Qt::QueuedConnection 2
Слот вызывается когда элемент управления возвращает управление в цикл обработки событий в потоке получателя. Слот выполняется в потоке получателя.


у меня поток не использует контролы и цикл обработки событий. Или это неважно ?

Сообщение отредактировал Алексей1153 - 24.1.2013, 9:52
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
iReset
  опции профиля:
сообщение 24.1.2013, 10:40
Сообщение #8


Участник
**

Группа: Участник
Сообщений: 178
Регистрация: 6.6.2012
Пользователь №: 3414

Спасибо сказали: 23 раз(а)




Репутация:   2  


Цитата(Алексей1153 @ 24.1.2013, 10:57) *
выходит, если указать Qt::QueuedConnection , то аргументы по значению можно передавать без синхронизации
а вот указатели на локальные данные при Qt::QueuedConnection точно нельзя по определению
Все можно передавать безопасно, только пользоваться с оглядкой :).

Цитата(Алексей1153 @ 24.1.2013, 10:57) *
так, а это что за комиссия )
Цитата
Qt::QueuedConnection 2
Слот вызывается когда элемент управления возвращает управление в цикл обработки событий в потоке получателя. Слот выполняется в потоке получателя.

Судя по оригиналу
Цитата
The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.
тут неправильный перевод. Должно быть
Цитата
Слот вызывается, когда управление возвращается циклу обработки событий в потоке получателя. Слот выполняется в потоке получателя.


Цитата(Алексей1153 @ 24.1.2013, 10:57) *
у меня поток не использует контролы и цикл обработки событий. Или это неважно ?
Ну контролы фиг с ними, а как ты без цикла обработки событий хочешь получить сигнал? Если поток на основе QThread, то он сам запускает свой цикл обработки событий (тут, второй абзац).
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 24.1.2013, 10:42
Сообщение #9


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


с циклом - понятно, ок

Ну, видимо, класс потока сам и запустил петлю. Я сам явно не запускал
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Авварон
  опции профиля:
сообщение 24.1.2013, 22:04
Сообщение #10


Студент
*

Группа: Участник
Сообщений: 99
Регистрация: 26.4.2009
Пользователь №: 709

Спасибо сказали: 14 раз(а)




Репутация:   0  


iReset
Всё там у QString нормально. У шаред классов атомарно копирование - при передаче строки в поток мы получаем 2 копии с рефкаунтом 2.
При попытке изменить строку делается detach() - если счетчик ссылок больше 2х, то создается новая дата, туда копируется содержимое (заметь, это всё обращения на чтение), затем делается deref() оригиналу и только после этого идет изменение строки.
Самое плохое, что может случиться - это если 2 потока сделают детач() "одновременно" - тогда будет создано еще 2 копии, а исходник будет уничтожен при deref() той строки, что закончила detach() последней. Но эта ситуация достаточно маловероятна и чревата только падениями производительности.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 25.11.2024, 13:39