Size: a a a

2020 November 11

AM

Alexander Malkov in pro.cxx
Alexander Zaitsev
вопросы должны начинаться с момента "А как её собрать то"
я где-то у них там читал, что под мак они не реализовывают ее
источник

AM

Alexander Malkov in pro.cxx
хотя, сейчас может что и изменилось..
источник

m

magras in pro.cxx
Valentin Kornienko
Хм, внезапно. А как корректно тогда реализовать when_all?
Опиши какую семантику ты хочешь от when_all.
источник

VK

Valentin Kornienko in pro.cxx
magras
Опиши какую семантику ты хочешь от when_all.
Мысль такая, чтобы передать пачку Tasks на выполнение ему и resume корутине, в которой when_all  был создан и запущен только по окончанию выполнения всех задач
источник

VK

Valentin Kornienko in pro.cxx
Т.е. Такая-же как у cppcoro::when_all, только у задач, которые передаются на выполнение- initial_suspend возвращает suspend_newer
источник

m

magras in pro.cxx
Valentin Kornienko
Мысль такая, чтобы передать пачку Tasks на выполнение ему и resume корутине, в которой when_all  был создан и запущен только по окончанию выполнения всех задач
Кажется makeTaskSequence делает именно это, нет?
источник

VK

Valentin Kornienko in pro.cxx
magras
Кажется makeTaskSequence делает именно это, нет?
Да, верно, но при этом происходит возврат на функцию уровнем выше, которая в свою очередь тоже может сделать makeTaskSequence т.к. не приостановлена
источник

VK

Valentin Kornienko in pro.cxx
Т.е. проблема, похоже в том, что я пытаюсь стеклесс корутины использовать как стекфул, или нет?
источник

VK

Valentin Kornienko in pro.cxx
И не могу приостановиться там, где необходимо
источник

m

magras in pro.cxx
Valentin Kornienko
Т.е. Такая-же как у cppcoro::when_all, только у задач, которые передаются на выполнение- initial_suspend возвращает suspend_newer
> When the returned awaitable is awaited, it will co_await each of the input awaitables on the current thread. Once the first awaitable suspends, the second task will be started, and so on. The operations execute concurrently until they have all run to completion.

Судя по описанию они создают миниатюрный однопоточный рантайм, чтобы конкурентно дожидаться переданных awaitable.
источник

VK

Valentin Kornienko in pro.cxx
magras
> When the returned awaitable is awaited, it will co_await each of the input awaitables on the current thread. Once the first awaitable suspends, the second task will be started, and so on. The operations execute concurrently until they have all run to completion.

Судя по описанию они создают миниатюрный однопоточный рантайм, чтобы конкурентно дожидаться переданных awaitable.
Т.е. я правильно понимаю, что у них никакой магии нет и если у меня есть расшаренный ресурс между Tasks, переданными в when_all к которому нужен уникальный доступ - то синхронизироваться надо отдельно и when_all не причем?
источник

m

magras in pro.cxx
Valentin Kornienko
Т.е. я правильно понимаю, что у них никакой магии нет и если у меня есть расшаренный ресурс между Tasks, переданными в when_all к которому нужен уникальный доступ - то синхронизироваться надо отдельно и when_all не причем?
Быстро отвечу на этот вопрос.

Нет, так как рантайм однопоточный: it will co_await each of the input awaitables *on the current thread*
источник

VK

Valentin Kornienko in pro.cxx
Once the first awaitable suspends, the second task will be started, and so on.
Т.е:
void runAll
->await_suspend Task1->
return to runAll
->restore from Task1
->await_suspend Task2
...

?
источник

m

magras in pro.cxx
Valentin Kornienko
Once the first awaitable suspends, the second task will be started, and so on.
Т.е:
void runAll
->await_suspend Task1->
return to runAll
->restore from Task1
->await_suspend Task2
...

?
Нет, это немного по-другому работает. Пока таски не спаунят свои трэды они не могут одновременно исполнятся. По сути однопоточный рантайм работает как-то так:

void run(tasks) {
 std::queue queue(tasks);
 while (!queue.empty()) {
   t = queue.pop_front();
   t.resume();
   if (!t.done)
     queue.push_back(t);
 }
}

То есть он просто в цикле исполняет таски. Если таска заблокировалась, кладем ее в конец очереди и берем следующую таску.
источник

GN

Gleb Nazarets in pro.cxx
соррян, черновики)
источник

VK

Valentin Kornienko in pro.cxx
magras
Нет, это немного по-другому работает. Пока таски не спаунят свои трэды они не могут одновременно исполнятся. По сути однопоточный рантайм работает как-то так:

void run(tasks) {
 std::queue queue(tasks);
 while (!queue.empty()) {
   t = queue.pop_front();
   t.resume();
   if (!t.done)
     queue.push_back(t);
 }
}

То есть он просто в цикле исполняет таски. Если таска заблокировалась, кладем ее в конец очереди и берем следующую таску.
Хм, интересно. Получается, там реализация отличается от того, что я скидывал
источник

VK

Valentin Kornienko in pro.cxx
Т.е. тут очередь задач выбирается, пока все задачи не будут готовые(а готовность определяется счетчиком)
источник

m

magras in pro.cxx
Valentin Kornienko
Хм, интересно. Получается, там реализация отличается от того, что я скидывал
На самом деле я могу ошибаться в том как устроен cppcoro. Я смотрел его кусками и конкретно when_all не ковырял. Но по описанию и своему опыту я бы сказал что должно быть реализовано примерно так как я описал выше.
источник

VK

Valentin Kornienko in pro.cxx
понял. Буду дальше еще смотреть, переосмыслить when_all попробую. Спасибо!
источник

m

magras in pro.cxx
magras
Нет, это немного по-другому работает. Пока таски не спаунят свои трэды они не могут одновременно исполнятся. По сути однопоточный рантайм работает как-то так:

void run(tasks) {
 std::queue queue(tasks);
 while (!queue.empty()) {
   t = queue.pop_front();
   t.resume();
   if (!t.done)
     queue.push_back(t);
 }
}

То есть он просто в цикле исполняет таски. Если таска заблокировалась, кладем ее в конец очереди и берем следующую таску.
Еще я лукавлю и без реактора (или аналога) таску нормально не заблокировать. В примере выше я просто дергаю не завершившуюся таску в цикле, что плохо работает в плюсовой архитектуре. Но я не готов сейчас рассказывать как построить свой рантайм с корутинами и io от начала до конца.
источник