Это одно и то же. Сопрограммы, конечно, разные бывают (вот когда-то еще в детстве я читал про них на Форте, user-space threads - тоже они, и я как-то даже делал свою реализацию), но вот конкретно такие, которые имеются в виду в С++ и Расте - функции с интерфейсом async/await.
Еще один вариант их представить - это несколько лямбд с общим контекстом. Запускается первая лямбда, она работает-работает пока не доходит до слова await. На этом месте она присоединяет к ожидаемому фьючеру лямбду-продолжение и возвращается. Когда фьючер будет готов, шедулер вызовет лямбду-продолжение и все продолжится. Когда же лямбда встречает слово return, она не просто так возвращается, а сначала сигналит в привязанный к контексту промиз/фьючер и освобождает контекст (выдывая деструкторы для всех объектов в нем).
Тут есть интересный момент: что если мы вызываем другую функцию, которая может внутри себя сделать await? Тогда та функция вернется в нашу, когда ее значение еще не готово. Ответ такой, что так делать не разрешается. Нельзя напрямую вызвать другую функцию, которая будет делать await, потому что та функция в таком разе обязана быть асинхронной. То есть, ее вызов транслируется в создание контекста и промиза/фьючера вызываемой асинхронной функции, привязывание к этому фьючеру своей лямбды-продолжения, шедуленье первой лямбды от новой функции, и возвращение из текущей лямбды.
no subject
Date: 2021-06-22 05:27 (UTC)Еще один вариант их представить - это несколько лямбд с общим контекстом. Запускается первая лямбда, она работает-работает пока не доходит до слова await. На этом месте она присоединяет к ожидаемому фьючеру лямбду-продолжение и возвращается. Когда фьючер будет готов, шедулер вызовет лямбду-продолжение и все продолжится. Когда же лямбда встречает слово return, она не просто так возвращается, а сначала сигналит в привязанный к контексту промиз/фьючер и освобождает контекст (выдывая деструкторы для всех объектов в нем).
Тут есть интересный момент: что если мы вызываем другую функцию, которая может внутри себя сделать await? Тогда та функция вернется в нашу, когда ее значение еще не готово. Ответ такой, что так делать не разрешается. Нельзя напрямую вызвать другую функцию, которая будет делать await, потому что та функция в таком разе обязана быть асинхронной. То есть, ее вызов транслируется в создание контекста и промиза/фьючера вызываемой асинхронной функции, привязывание к этому фьючеру своей лямбды-продолжения, шедуленье первой лямбды от новой функции, и возвращение из текущей лямбды.