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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Не блокирующий обмен данными между потоками  (Прочитано 9872 раз)
JamS007
Гость
« : Июль 28, 2010, 22:56 »

Приветствую, господа.

Задача: Есть сервер. При инициализации создаю пул служебных потоков. (-1 от количества ядер на машине или 1, если ядро одно). В основном потоке подключаються клиенты и читаються запросы от них. Также в основном потоке декодируються запросы от клинтов, и в зависимости от запроса "напрягаеться" служебный поток. Служебные потоки должны выполнять потенциально медленные задачи (чтение/запись с HDD, всевозможные проверки, и т.д.)

Хочу сделать максимально продуктивный сервер, в рамках Qt (другое не предлагать), поэтому, стараюсь комбинировать асинхронность с многопоточностью. Если есть идеи - с удовольствием выслушаю.

Цель: Среди задач выполняемых служебными потоками, есть такие, которые требуют подтверждения успешного выполнения. И тут возникает проблема:

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

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

Заранеее спасибо, даже за внимание Улыбающийся
Записан
BlackTass
Гость
« Ответ #1 : Июль 29, 2010, 00:46 »

Ну не блокировать основной поток можно посредством проброса сигнала из рабочего в основной по завершении. Главное только таски между собой различить по какому-нить ид.

Про очередь не понял вопроса. В том порядке в каком приходят в том и ставьте, ну или если есть приоритеты у тасков, то тасуйте слегка очередь/делайте несколько очередей (как в консульствах).
Записан
JamS007
Гость
« Ответ #2 : Июль 29, 2010, 10:59 »

Про сигналы я уже думал. Они действительно не блокируют основной поток поток, но на сигналы не приходит ответ, тоесть сигнал выслан, и все, как он там дальше будет обрабатыватся уже не известно.

Можно конечно сделать такуй связку сигналов:

Основной поток  --- (запрос) ---> дочерний поток
Дочерний поток  --- (ответ)   ---> основной поток

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

Тут, конечно, тоже можно выкрутиться, например прысилать какой-нибудь идентификатор запроса, но у меня команды записываються в ByteArray, и он весит порядка 40кб. (Знаю, много) И таскать каждый раз эту команду в поток и назад не хочеться.

Есть идеи?
Записан
BlackTass
Гость
« Ответ #3 : Июль 29, 2010, 11:13 »

Я про это и имел в виду когда писал про ид. Основной поток присылает вместе с запросом его уникальный ид (который сам генерит банальным инкрементом). Дочерний поток присылает ответ вместе с этим идшником и основной поток уже смотрит что вообще за команда то была по ид.
Записан
SABROG
Гость
« Ответ #4 : Июль 29, 2010, 12:24 »

Стандартный метод вызвать слот из другого потока, который вышлет сигнал, когда данные или работа будет завершена. Тут только возникает проблема с контекстом локальных переменных, если их значения нужно восстановить после получения результата и продолжить некую логику зависящую от них и возвращенного значения (как это сделано в closure'ах).
« Последнее редактирование: Июль 29, 2010, 12:47 от SABROG » Записан
JamS007
Гость
« Ответ #5 : Июль 29, 2010, 16:47 »

SABROG, спасибо, познавательная статейка. В принципе так и думал делать Улыбающийся

Еще один вопрос: есть 2 потока. Пусть в первом из них будет динамически создана переменная, тоесть память возметься из кучи, а в самом потоке будет только указатель на нее. Сможет ли второй поток обратиться по переданному указателю к этой переменной, если поток 1 находиться в ожидании и не работает. Я имею ввиду, кокой из потоков в конце концов обработает обращение к памяти, тот что запрашивает переменную из памяти, или тот, что ее создал?

По другому можно сформульровать вопрос так: динамические переменные создаються адресном пространстве потока, или в общем? И если в общем, то можно ли к ним получить доступ из разных потоков?
Записан
SABROG
Гость
« Ответ #6 : Июль 29, 2010, 16:55 »

В принципе через локальный QEventLoop можно симулировать сохранение локальных переменных и ожидание результатов из слота.
Записан
BRE
Гость
« Ответ #7 : Июль 29, 2010, 16:56 »

По другому можно сформульровать вопрос так: динамические переменные создаються адресном пространстве потока, или в общем? И если в общем, то можно ли к ним получить доступ из разных потоков?
Все потоки работают в одном адресном пространстве.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Август 02, 2010, 13:43 »

По другому можно сформульровать вопрос так: динамические переменные создаються адресном пространстве потока, или в общем? И если в общем, то можно ли к ним получить доступ из разных потоков?
В общем, если "только чтение" то проблем никаких
Записан
Barmaglodd
Гость
« Ответ #9 : Август 02, 2010, 14:17 »

В общем, если "только чтение" то проблем никаких
Угу, у вас все операции с памятью как транзакции в БД работают? Особенно интересно в контексте конструктора сложного объекта.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Август 02, 2010, 14:42 »

Угу, у вас все операции с памятью как транзакции в БД работают? Особенно интересно в контексте конструктора сложного объекта.
До чого тут транзакцii БД?  Улыбающийся  Не понял Вашего вопроса, поясните на примере
Записан
Barmaglodd
Гость
« Ответ #11 : Август 02, 2010, 15:08 »

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


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