Russian Qt Forum
Июнь 22, 2024, 18:28 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: ThreadTeam  (Прочитано 6137 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Февраль 04, 2016, 09:01 »

Добрый день

Почти каждая тема "многопоточности" сваливается в проблемы синхронизации и/или классы QtConcurrent. Вот стало интересно - а можно как-то без всего этого, чисто на слот/сигнал?

У нас есть N задач которые мы хотим скормить какому-то числу ниток (обычно = числу ядер). При этом обычный ф-ционал: остановить, продолжить, отменить. Принципиально не используем никаких примитивов синхронизации, даже любимых мною атомиков. И делаем "по-богатому": задача стартовала/закончилась- сигнал в UI, все отмены/продолжения - тоже испускаем сигналы. Конечно так будут накладные расходы, но мы считаем задачи у нас достаточно жирные (хорошие доли секунды и больше). В общем, за скоростью не гонимся

Чтобы юзать надо создать нужные слоты. Пример
Код
C++ (Qt)
// создаем "бригаду"
CControl * ctl = new CControl(QThread::idealThreadCount()); .
 
// слот который считает,  (только он выполняется в рабочих нитках, все остальные в главной)
ctl->Connect2Calc(this, &CTestWin::SlotCalc);
 
// слот скармливающий очередную задачу
QObject::connect(ctl, &CControl::SignalTaskGet, this, &CTestWin::SlotGetTask);
 
// слот "задача началась"
QObject::connect(сtl, &CControl::SignalTaskBegin, this, &CTestWin::SlotTaskBegin);
 
// слот "задача сделана"
QObject::connect(ctl, &CControl::SignalTaskDone, this, &CTestWin::SlotTaskDone);
 
// слот "нитка не имеет больше задач"
QObject::connect(ctl, &CControl::SignalNoTask, this, &CTestWin::SlotNoTask);
 
// отслеживает останов, пуск, отмена и готово
QObject::connect(ctl, &CControl::SignalStateChanged, this, &CTestWin::SlotStateChanged);
 
// погнали считать
ctl->Go();
 
Окончание ловим в SlotStateChanged. В аттаче пример с UI (pro файл имеется)

Это все, благодарю за внимание
« Последнее редактирование: Февраль 04, 2016, 09:05 от Igors » Записан
poru
Самовар
**
Offline Offline

Сообщений: 103


Просмотр профиля
« Ответ #1 : Февраль 04, 2016, 15:43 »

Мне кажется все перемудрено. Давайте уточним. Есть 100 неких вычислений. Есть 4 потока. Запускаем потоки одновременно. В каждом потоке решается только одно вычисление. Как только оно закончилось то в этот поток закидываем следующее вычисление. Правильно? Тогда у меня вопрос - само вычисление есть самостоятельный объект с известным методом или как некоторая функция произвольного класса?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Февраль 04, 2016, 16:04 »

Давайте уточним. Есть 100 неких вычислений. Есть 4 потока. Запускаем потоки одновременно. В каждом потоке решается только одно вычисление. Как только оно закончилось то в этот поток закидываем следующее вычисление. Правильно?
Да, все верно

Тогда у меня вопрос - само вычисление есть самостоятельный объект с известным методом или как некоторая функция произвольного класса?
Код вычисления - любой слот любого класса, задается в Connect2Calc. Этот слот получает на вход аргумент void * data, это данные для обсчета. Да, я знаю, есть QRunnable, но не лежит к нему душа (жабой отдает). В конце-концов, данные могут быть и POD структурой
Записан
poru
Самовар
**
Offline Offline

Сообщений: 103


Просмотр профиля
« Ответ #3 : Февраль 05, 2016, 15:01 »

Вот какие у меня замечания. Как нам известно "сигнал" предназначен, что бы сообщать об произошедших изменениях, а "слот" есть реакция на эти изменения. В Вашем случае сигналы SignalTaskGet, SignalTaskCalc не сообщают об изменения, а вызывают конкретные действия. Это не соответствует идеологии сигналов/слотов. И от этого такая запутанность.

И для чего таскать по всем вызовам ctl и thread?
« Последнее редактирование: Февраль 05, 2016, 15:04 от poru » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Февраль 05, 2016, 16:48 »

Вот какие у меня замечания. Как нам известно "сигнал" предназначен, что бы сообщать об произошедших изменениях, а "слот" есть реакция на эти изменения. В Вашем случае сигналы SignalTaskGet, SignalTaskCalc не сообщают об изменения, а вызывают конкретные действия. Это не соответствует идеологии сигналов/слотов. И от этого такая запутанность.
Возможно это впечатление оттого что CThread публичный класс и есть возможность его наследования (хотя нужно это редко). Поэтому чтение хедера начинается "с самых потрохов"  Улыбающийся

И для чего таскать по всем вызовам ctl и thread?
ctl - на мой вкус опрятнее чем приводить sender'a. А thread может оказаться необходимым. Напр известно что неск задач должны выполняться только последовательно - ну мы их в одну нитку и закинем. Или вообще, какой-то нитке не будем давать никаких задач (пока).

Др интересные возможности: задача может порождать др задачи, вообще число задач заранее неизвестно. Или задача требует чтобы на момент ее старта др задачи были уже выполнены. И.т.п. Такие вещи здесь делаются без труда.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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