Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Конкурентное программирование, неблокирующий вызов функций 
:(
    Опции темы
SABROG
  Дата 29.7.2010, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Есть такая идея. Один поток отвечает за прием соединений от клиентов и общение по некому протоколу, второй поток выполняет "тяжелую" работу для каждого клиента.
Соответственно первый поток должен быть всегда разгружен, чтобы обрабатывать подключения пользователей.
Предположим пользователь попросил сервер выдать ему некий кусок данных из БД "SELECT" запросом. В БД много записей и она ели шорохается, то есть ответ выборки может прийти через минут эдак 5.

Хочу чтобы логика была такой:

Код

void foo()
{
    int var1 = 2;
    float var2 = 3.0;
    int var3 = doLongStuff();
    if (var1 == 2 && var3)
        doSomething();
}


Но работало так:

 foo() объявляет локальные переменные и вызывает doLongStruff() из другого потока, но при этом функция возвращает управление обратно не дожидаясь выполнения тяжелой работы. Когда другой поток завершает тяжулую работу, то сигнализирует каким-то образом первому потоку об этом. При этом первый поток получает результат функции и восстанавливает локальные переменные, которые были объявлены до вызова doLongStuff(), чтобы продолжить работу. В результате функция должна разделиться на 2 части:

Код

void foo()
{
    int var1 = 2;
    float var2 = 3.0;
    doLongStuff(); // помимо самого вызова функции тут как-то нужно сохранить stack-frame с локальными переменными
    ... // дальше поток возвращается в цикл обработки сообщений и соединений от клиентов

Код

void foo_part2(int resultFromDoLongStuff)
{
    restoreLocalVariables();
    if (var1 == 2 && resultFromDoLongStuff)
        doSomething();
}


Как такое обычно решают?


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
SenkraD
Дата 29.7.2010, 14:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 3.2.2006
Где: Украина::Киев

Репутация: 2
Всего: 23



SABROG,  что кроме QT вам доступно? Какие целевые платформы?
Вообщем, это обыкновенный асинхронно-событийный сценарий. Под виндовс IOCompletionPorts думаю самое то,
а что под *NIX не помню.

Это сообщение отредактировал(а) SenkraD - 29.7.2010, 14:51


--------------------
 Имеющий язык - да не убоится спросить! 
user posted image
PM MAIL ICQ   Вверх
Abyx
Дата 29.7.2010, 14:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 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
PM MAIL   Вверх
SenkraD
Дата 29.7.2010, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 3.2.2006
Где: Украина::Киев

Репутация: 2
Всего: 23



Abyx +1, если доступен boost


--------------------
 Имеющий язык - да не убоится спросить! 
user posted image
PM MAIL ICQ   Вверх
SABROG
Дата 29.7.2010, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(SenkraD @  29.7.2010,  14:49 Найти цитируемый пост)
Вообщем, это обыкновенный асинхронно-событийный сценарий.

Он не совсем обыкновенный. Дело даже не в сокетах, это я для примера взял. С событиями в Qt проблем нет, даже используя обычное API ОС это можно сделать. Проблема как через эти существующие системы реализовать такой функционал, при котором  одна функция вызывает другую и не ждет пока она выполнится (это не вопрос). Сообщить о том, что функция завершилась в другой поток (тоже не вопрос). Передать при этом результат функции (тоже возможно). Восстановить стек-фрейм, чтобы продолжить выполнение функции в определенном контексте с локальными переменными, которые существовали на момент вызова долгой функции (тут проблема). Единственный вариант, который я вижу - передавать в долгую функцию еще и список/структуру с переменными. Или сохранять их в какойм нибудь контейнере, чтобы организовать очередь ожиданий результатов функций, если вызовов было несколько. И вся эта система выглядить довольно некрасивой.

Цитата(Abyx @  29.7.2010,  14:53 Найти цитируемый пост)
    async_do_some(...., [](....){
        ......
        async_do_some(...., [](....){
            ......
            async_do_some(...., [](....){

После первого вызова async_do_some() поток будет ждать результат прежде чем вызовет второй вложенный async_do_some()? Если да, то это не приемлемо, после вызова async_do_some() должен произойти возврат из функции, чтобы делать что-то другое, а не простаивать ожидая результатов от функций.

Это сообщение отредактировал(а) SABROG - 29.7.2010, 15:00


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Abyx
Дата 29.7.2010, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



также стоит почитать про coroutines, вроде на этом форуме уже писали

Добавлено через 58 секунд
впрочем вы уже читали
http://forum.vingrad.ru/forum/topic-295443...tine/index.html
PM MAIL   Вверх
djamshud
Дата 29.7.2010, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 8
Всего: 39



Если хотите, чтобы стек сам сохранялся и разворачивался обратно, попробуйте setjmp/longjmp. Но с ними нужно быть очень осторожным.


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
SABROG
Дата 29.7.2010, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Интересно, такое вообще бывает "многопоточные не блокирующие замыкания"? Где функция одного потока имеющая замыкание в другом потоке могла продолжить выполняться с той точки где был вызов определенного замыкания, при этом восстанавливался контекст с локальными переменными.

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


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
mes
Дата 29.7.2010, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



вместо функций функторы с колбяками.. но без доп. средств много лишнего (однообразного ) кода.. 



--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 29.7.2010, 20:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



еще std::async() гляньте. чтоб велосипеды не городить.
PM WWW   Вверх
SABROG
Дата 30.7.2010, 11:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(boostcoder @ 29.7.2010,  20:21)
еще std::async() гляньте. чтоб велосипеды не городить.

Глянул. Принцип остался тот же, создать асинхронную задачу не вопрос, хоть в одном потоке, хоть в другом. Вопрос в том, как не ожидая завершения этих задач получить через час её результат и стек с переменными. В случае с Qt я вижу только один способ - локальный QEventLoop. Уровень вложенности может быть большим (тут надо следить за расходом памяти), стек с локальными переменными остается, работа сигналов и слотов не блокируется.  По завершению какой-либо задачи происходит выход из локального цикла событий, что позволяет нам продолжить выполнять вызванную функцию с прерванного момента в любое время.

Другой вариант использовать QFuture + QFutureWatcher. Но его принцип действия равносилен схеме: асинхронный вызов функции из другого потока + сигнал о завершении функции. Никакого продолжения прерванной функции с сохранением контекста локальных переменных нет.

Больше всего по смыслу подходят closures, но информации об их работе в разных потоках и асинхронности мало.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
HellStranger
Дата 30.7.2010, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 1.9.2009

Репутация: -2
Всего: -1



Цитата(SenkraD @  29.7.2010,  14:49 Найти цитируемый пост)
SABROG,  что кроме QT вам доступно? Какие целевые платформы?Вообщем, это обыкновенный асинхронно-событийный сценарий. Под виндовс IOCompletionPorts думаю самое то,а что под *NIX не помню.


Не самое умное решение... Поток поддержки порта завершения ввода/вывода нельзя загружать длительными операциями! Советую почитать Джефри Рихтера. Глава что-то около 20-ой... Пулы потоков. Там популярно объясняется и про порт завершения ввода/вывода и про таймер ожидания... И о том, как заставиить произвольный поток выполнить код, который тебе нужно...

Добавлено @ 12:39
Цитата(SABROG @  29.7.2010,  14:33 Найти цитируемый пост)
Есть такая идея. Один поток отвечает за прием соединений от клиентов и общение по некому протоколу, второй поток выполняет "тяжелую" работу для каждого клиента.


Задача решается влёт с помощью PostThreadMessage. Поток получения запросов от клиентов передаёт с помощью указанной фукции сообщение и параметры потоку обработки с помощью PostThreadMessage. Работает замечтательно, использую этот механизм практически во всех приложениях.

Хотя, если нужно кроссплатформенное решение, то оно будет под каждой осью своё... Да и сомневаюсь я, что под никсами есть такие вкусности...

Это сообщение отредактировал(а) HellStranger - 30.7.2010, 12:44
PM MAIL   Вверх
mes
Дата 30.7.2010, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SABROG @  30.7.2010,  10:14 Найти цитируемый пост)
икакого продолжения прерванной функции с сохранением контекста локальных переменных нет.


Цитата(mes @  29.7.2010,  18:09 Найти цитируемый пост)
функторы с колбяками.

smile




--------------------
PM MAIL WWW   Вверх
HellStranger
Дата 30.7.2010, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 1.9.2009

Репутация: -2
Всего: -1



Как и ожидалось, в никсах такого простого и элегантного решения проблемы нету, но есть libpthread, о которой знающие люди говорят, что помжет... smile
PM MAIL   Вверх
boostcoder
Дата 30.7.2010, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



дважды прочел тему, и никак не могу понять что именно SABROGу нужно smile 
первое что пришло в голову из того что понял - сопрограммы.
у автора азио в блоге об этом превосходно рассказано: 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
PM WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0606 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.