Re[39]: cppcms
От: Evgeny.Panasyuk Россия  
Дата: 25.09.14 19:32
Оценка:
Здравствуйте, artelk, Вы писали:

A>На сколько удалось распарсить, у каждого рабочего потока своя очередь.


Да.

A>Нафига?


Это демонстрация эмуляции await, а конкретно перекидывание управления между потоками, а не какой-то реальный код. Scheduling может быть каким угодно.
Например вот тут два примера использования корутин с простейшим win32 gui interaction:
http://rsdn.ru/forum/philosophy/5215367.1
Автор: Evgeny.Panasyuk
Дата: 29.06.13

http://rsdn.ru/forum/philosophy/5223345.1
Автор: Evgeny.Panasyuk
Дата: 08.07.13


A>Кстати, а почему он один?


Кто один? Один рабочий поток на "пул"? А зачем больше? Цель — показать как корутина может мигрировать между потоками/контекстами, двух потоков/контекстов для этого достаточно.

A>Остальные ядра процессора тупо простаивать будут, в то время как к нашему сервису целая толпа клиентских запросов в очередь выстроилась?


Это не демонстрация реализации сервиса.

A>По умолчанию, после асинхронной IO операции, управление возвращается в исходный поток пула, так? А если он будет занят чем-то другим к этому моменту (какой-нибудь длительной синхронной операцией), ждать пока освободится


В этом конкретном примере действие добавляется в очередь сообщений потока.

A>(в то время как остальные потоки пула могут быть свободны)?


Если потоков для "возврата" несколько — то можно делать какую угодно балансировку, но это уже детали работы планировщика, а не эмуляции await.
Грубо говоря, этот await цепляется к любой асинхронной операции которая может принять handler, а как и где именно эти операции вращаются — дело ортогональное.
Например, C#'ский await работает не только для сетевых или gui приложений. В то же время эти сетевые и gui приложения работали и без await'а, и у них были уже готовые планирощики — await просто помогает упростить код, сам по себе он потоки не распределяет.

A>Или нужно не давать потоку ничего делать, пока операция не закончится? Так это же блокировкой называется, будет по потоку на запрос.


Нет блокировки, например это видно из шапки лога:
Thread ID=7fe0cff85700 Coro ID=0: entry_point{A}
Thread ID=7fe0cff85700 Coro ID=1: foo{A}, arg=10
Thread ID=7fe0cff85700 Coro ID=2: foo{A}, arg=20

Когда корутина Coro ID=1 дошла до точки foo{A} — она начала await'ить асинхронную операцию. Но в это время поток не заблокирован (это видно по Thread ID), а перешёл к выполнению корутины Coro ID=2.

A>А если не по умолчанию, нужно указать конкретный поток в котором нужно будет продолжится? Дык, та же проблема.


В каком смысле? То есть в какой конкретно поток нужно вернуться будет зависеть, например, от того какой свободен? Тоже не проблема — это ортогональные детали планировщика.

EP>>// await is not limited by "one level" as in C#

A>Всмысле?

Функция foo вызывает bar. В C# пришлось бы ставить async на bar, а тут нет. То есть вызов await может находится на какой угодно глубине, в отличии от C# (где это возможно только в пределах async методов).
Это позволяет, например, взять обычный синхронный код, передать ему объекты-stream'ы с await'ом внутри — и всё заработает без изменений.
http://rsdn.ru/forum/philosophy/5206735.1
Автор: Evgeny.Panasyuk
Дата: 21.06.13


A>Тут создание и блокировка потока будет, правильно?


Создание будет, а блокировки — нет.

A>Task.Delay(N) работает хитрее — текущий поток освобождается и возвращается в пул. Продолжение будет добавлено в очередь заданий через N ms. Нет такого, что на каждый Task.Delay тратится по потоку на ожидание\засыпание.


Это всего лишь пример какого-то асинхронного действия. В том же коде есть post_task, который использует уже готовый поток. И вообще всё может работать в одном потоке.

EP>>// Full emulation of await feature from C# language in C++ based on Stackful Coroutines from

EP>>// Boost.Coroutine library.
A>Пока рано такие заголовки вставлять

Почему же? Эмуляция работает, синтаксис такой же, мощности даже больше чем в оригинале.

A>Мечталось погонять готовый сервис на предмет масштабируемости.


Для таких тестов ограничиваться await'ом не обязательно, корутины для реализации подобных сервисов можно использовать сами по себе, без эмуляции await.
В Boost.Asio даже есть готовые рецепты, например:
http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/spawn.html
http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp
char data[128];
for (;;)
{
    std::size_t length = my_socket.async_read_some(boost::asio::buffer(data), yield);
    boost::asio::async_write(my_socket, boost::asio::buffer(data, length), yield);
}


Лично тестировал
Автор: Evgeny.Panasyuk
Дата: 30.11.13
только запуск сотен тысяч корутин в одном потоке, вне контекста сети.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.