Здравствуйте, 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
только запуск сотен тысяч корутин в одном потоке, вне контекста сети.