![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| SABROG |
|
||||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Есть такая идея. Один поток отвечает за прием соединений от клиентов и общение по некому протоколу, второй поток выполняет "тяжелую" работу для каждого клиента.
Соответственно первый поток должен быть всегда разгружен, чтобы обрабатывать подключения пользователей. Предположим пользователь попросил сервер выдать ему некий кусок данных из БД "SELECT" запросом. В БД много записей и она ели шорохается, то есть ответ выборки может прийти через минут эдак 5. Хочу чтобы логика была такой:
Но работало так: foo() объявляет локальные переменные и вызывает doLongStruff() из другого потока, но при этом функция возвращает управление обратно не дожидаясь выполнения тяжелой работы. Когда другой поток завершает тяжулую работу, то сигнализирует каким-то образом первому потоку об этом. При этом первый поток получает результат функции и восстанавливает локальные переменные, которые были объявлены до вызова doLongStuff(), чтобы продолжить работу. В результате функция должна разделиться на 2 части:
Как такое обычно решают? |
||||||
|
|||||||
| SenkraD |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 3.2.2006 Где: Украина::Киев Репутация: 2 Всего: 23 |
SABROG, что кроме QT вам доступно? Какие целевые платформы?
Вообщем, это обыкновенный асинхронно-событийный сценарий. Под виндовс IOCompletionPorts думаю самое то, а что под *NIX не помню. Это сообщение отредактировал(а) SenkraD - 29.7.2010, 14:51 |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 1 Всего: 10 |
boost.asio
void Init() { ...... async_do_some(...., [](....){ ...... async_do_some(...., [](....){ ...... async_do_some(...., [](....){ ...... }); }); }); } Это сообщение отредактировал(а) Abyx - 29.7.2010, 14:55 |
|||
|
||||
| SenkraD |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 3.2.2006 Где: Украина::Киев Репутация: 2 Всего: 23 |
Abyx +1, если доступен boost
|
|||
|
||||
| SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Он не совсем обыкновенный. Дело даже не в сокетах, это я для примера взял. С событиями в Qt проблем нет, даже используя обычное API ОС это можно сделать. Проблема как через эти существующие системы реализовать такой функционал, при котором одна функция вызывает другую и не ждет пока она выполнится (это не вопрос). Сообщить о том, что функция завершилась в другой поток (тоже не вопрос). Передать при этом результат функции (тоже возможно). Восстановить стек-фрейм, чтобы продолжить выполнение функции в определенном контексте с локальными переменными, которые существовали на момент вызова долгой функции (тут проблема). Единственный вариант, который я вижу - передавать в долгую функцию еще и список/структуру с переменными. Или сохранять их в какойм нибудь контейнере, чтобы организовать очередь ожиданий результатов функций, если вызовов было несколько. И вся эта система выглядить довольно некрасивой.
После первого вызова async_do_some() поток будет ждать результат прежде чем вызовет второй вложенный async_do_some()? Если да, то это не приемлемо, после вызова async_do_some() должен произойти возврат из функции, чтобы делать что-то другое, а не простаивать ожидая результатов от функций. Это сообщение отредактировал(а) SABROG - 29.7.2010, 15:00 |
|||
|
||||
| Abyx |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 601 Регистрация: 3.11.2009 Репутация: 1 Всего: 10 |
также стоит почитать про coroutines, вроде на этом форуме уже писали
Добавлено через 58 секунд впрочем вы уже читали http://forum.vingrad.ru/forum/topic-295443...tine/index.html |
|||
|
||||
| djamshud |
|
|||
![]() Пердупержденный ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 23.11.2009 Репутация: 8 Всего: 39 |
Если хотите, чтобы стек сам сохранялся и разворачивался обратно, попробуйте setjmp/longjmp. Но с ними нужно быть очень осторожным.
-------------------- 'Cuz I never walk away from what I know is right Alice Cooper - Freedom |
|||
|
||||
| SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Интересно, такое вообще бывает "многопоточные не блокирующие замыкания"? Где функция одного потока имеющая замыкание в другом потоке могла продолжить выполняться с той точки где был вызов определенного замыкания, при этом восстанавливался контекст с локальными переменными.
Функция foo() вызывает замыкание в другом потоке, не ждет завершения и уходит делать другую работу, как только это работа завершена функция как-бы освобождается не надлого, чтобы проверить закончило ли свою работу замыкание из другого потока, если закончила, то контекст возвращается со всеми переменными и продолжается выполнение прерванной функции foo(). Если замыкание работу не завершило, то поток идет на следующий круг и делает какую-то другую работу. |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
вместо функций функторы с колбяками.. но без доп. средств много лишнего (однообразного ) кода..
|
|||
|
||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
еще std::async() гляньте. чтоб велосипеды не городить.
|
|||
|
||||
| SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Глянул. Принцип остался тот же, создать асинхронную задачу не вопрос, хоть в одном потоке, хоть в другом. Вопрос в том, как не ожидая завершения этих задач получить через час её результат и стек с переменными. В случае с Qt я вижу только один способ - локальный QEventLoop. Уровень вложенности может быть большим (тут надо следить за расходом памяти), стек с локальными переменными остается, работа сигналов и слотов не блокируется. По завершению какой-либо задачи происходит выход из локального цикла событий, что позволяет нам продолжить выполнять вызванную функцию с прерванного момента в любое время. Другой вариант использовать QFuture + QFutureWatcher. Но его принцип действия равносилен схеме: асинхронный вызов функции из другого потока + сигнал о завершении функции. Никакого продолжения прерванной функции с сохранением контекста локальных переменных нет. Больше всего по смыслу подходят closures, но информации об их работе в разных потоках и асинхронности мало. |
|||
|
||||
| HellStranger |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 107 Регистрация: 1.9.2009 Репутация: -2 Всего: -1 |
Не самое умное решение... Поток поддержки порта завершения ввода/вывода нельзя загружать длительными операциями! Советую почитать Джефри Рихтера. Глава что-то около 20-ой... Пулы потоков. Там популярно объясняется и про порт завершения ввода/вывода и про таймер ожидания... И о том, как заставиить произвольный поток выполнить код, который тебе нужно... Добавлено @ 12:39
Задача решается влёт с помощью PostThreadMessage. Поток получения запросов от клиентов передаёт с помощью указанной фукции сообщение и параметры потоку обработки с помощью PostThreadMessage. Работает замечтательно, использую этот механизм практически во всех приложениях. Хотя, если нужно кроссплатформенное решение, то оно будет под каждой осью своё... Да и сомневаюсь я, что под никсами есть такие вкусности... Это сообщение отредактировал(а) HellStranger - 30.7.2010, 12:44 |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
||||
|
||||
| HellStranger |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 107 Регистрация: 1.9.2009 Репутация: -2 Всего: -1 |
Как и ожидалось, в никсах такого простого и элегантного решения проблемы нету, но есть libpthread, о которой знающие люди говорят, что помжет...
|
|||
|
||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
дважды прочел тему, и никак не могу понять что именно SABROGу нужно
первое что пришло в голову из того что понял - сопрограммы. у автора азио в блоге об этом превосходно рассказано: http://blog.think-async.com/2010/03/potted...coroutines.html Добавлено через 3 минуты и 8 секунд и превосходный пример многопользовательского асинхронного сервера использующего сопрограммы. меньше 100 строк кода. http://blog.think-async.com/2009/07/wife-s...e-it-works.html |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |