Проблемы с использованием сопрограмм C ++ - PullRequest
1 голос
/ 08 ноября 2019

Я экспериментирую с сопрограммами 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 , пожалуйста, помогите.

1 Ответ

0 голосов
/ 08 ноября 2019

Для 2-й попытки я обнаружил, что забыл назначить задачу, возвращаемую лямбда-выражением, что приводит к разрушению задачи сразу после возврата лямбда-функции.

...