Я экспериментирую с сопрограммами C ++ с liburing .
Я разработчик JavaScript и пытаюсь реализовать такую функцию, как Promise.all
Моя первая попытка
template <typename T>
task<std::vector<T>> taskAll1(std::vector<task<T>> list) {
std::vector<T> result;
result.reserve(list.size());
for (auto&& t : list) {
result.push_back(co_await t);
}
co_return result;
}
задача изменена с gor_task . Я в основном заставляю task::promise_type::initial_suspend
возвращать suspend_never
, чтобы запускать сопрограммы по умолчанию.
Использование:
// async_delay: https://github.com/CarterLi/liburing-http-demo/blob/12af992d0d87a721bbe67bb67aee8e4b0e965114/async_coro.hpp#L68
// It waits some seconds asynchronously and then prints the number of seconds it waits.
task<bool> start() {
// TODO: less verbose code?
std::vector<task<int>> vec;
vec.emplace_back(async_delay(1));
vec.emplace_back(async_delay(2));
vec.emplace_back(async_delay(3));
co_await taskAll<int>(std::move(vec));
co_return true;
}
Код работает, как и ожидалось. Но если я переставлю порядок emplace_back
с, например, пусть async_delay(2)
предшествует async_delay(1)
, код все равно запускается, но останавливается в конце программы. Я знаю, что это потому, что задача async_delay(1)
решена до того, как ее ожидают, но я понятия не имею, как ее исправить.
Вторая попытка, которую я хочу сделать, - это перевод следующего кода JS в C ++
/** @param {Promise<any>[]} list */
function taskAll(list) {
return new Promise(resolve => {
const result = new Array(list.length);
let left = list.length;
list.forEach((p, i) => {
p.then(x => {
result[i] = x;
left--;
if (!left) resolve(result);
})
});
});
}
Код C ++
// completion: https://github.com/CarterLi/liburing-http-demo/blob/12af992d0d87a721bbe67bb67aee8e4b0e965114/task.hpp#L78
// It's like JS Promise and can be awaited directly without calling an async function
template <typename T>
task<std::vector<T>> taskAll(std::vector<task<T>> list) {
std::vector<T> result(list.size());
size_t left = list.size();
completion<std::vector<T>> promise;
for (size_t i=0; i<list.size(); ++i) {
[&, i]() mutable -> task<bool> {
result[i] = co_await list[i];
left--;
if (!left) promise.resolve(std::move(result));
co_return true;
}();
}
co_await promise;
co_return result;
}
Код немедленно падает. Асинхронный код действительно трудно отладить, и я сдался.
Полный код можно найти в Github , пожалуйста, помогите.