0Pricing
C++ Academy · Урок

Асинхронные задачи и типы awaiter

Составляйте асинхронные задачи с пользовательскими типами awaiter и promise.

«Асинхронные задачи и типы awaiter» — бесплатный урок C++ Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.

Асинхронные корутины

Асинхронная задача приостанавливается во время ввода-вывода и возобновляет выполнение после завершения операции. Сочетайте co_await с асинхронными интерфейсами, чтобы писать асинхронный код без обратных вызовов.

Эскиз типа Task

Task оборачивает асинхронную корутину. Он поддерживает co_await для построения цепочек.

template <typename T>
struct Task {
    struct promise_type;
    std::coroutine_handle<promise_type> handle;
    // ...
};

Механика co_await

Когда компилятор встречает co_await expr, он ожидает, что expr будет ожидаемым объектом. У ожидаемого объекта есть три метода:

  • await_ready() — значение false для приостановки и true, чтобы её пропустить
  • await_suspend(handle) — действия во время приостановки
  • await_resume() — значение, передаваемое вызывающему коду

Пример ожидаемого объекта: Sleep

Ожидаемый объект, который планирует возобновление выполнения после задержки.

struct Sleep {
    std::chrono::milliseconds duration;
    bool await_ready() const { return false; }
    void await_suspend(std::coroutine_handle<> h) {
        std::thread([h, this] {
            std::this_thread::sleep_for(duration);
            h.resume();
        }).detach();
    }
    void await_resume() {}
};

Task<void> example() {
    co_await Sleep{500ms};
    std::cout << "after 500ms";
}

Ожидаемый объект для HTTP

Библиотеки предоставляют ожидаемые объекты для HTTP-запросов, таймеров и файлового ввода-вывода. Объединяйте их так же, как обычные синхронные вызовы.

Task<std::string> fetch() {
    auto data = co_await http_get("/api/data");
    co_return data;
}

Объединение задач

Ожидание одной задачи внутри другой связывает их в цепочку. Внешняя задача приостанавливается до завершения внутренней.

Task<int> outer() {
    int x = co_await inner_a();
    int y = co_await inner_b();
    co_return x + y;
}

Параллельные задачи

Для параллельной асинхронной работы запускайте задачи, не ожидая немедленного завершения каждой из них, а затем дождитесь их всех.

Task<int> sum_tasks() {
    auto a = inner_a();
    auto b = inner_b();
    int x = co_await a;
    int y = co_await b;
    co_return x + y;
}

Распространение исключений

Исключения, выброшенные внутри асинхронной задачи, могут быть сохранены в unhandled_exception объекта promise и повторно выброшены на стороне ожидающего кода.

Отмена

Стандартная библиотека пока не предоставляет примитив отмены. Библиотеки, такие как cppcoro и boost.cobalt, реализуют собственные варианты — обычно с помощью токенов отмены или источников остановки.

Интеграция с Boost.Asio

Asio изначально поддерживает корутины. Используйте co_await с операциями async_read, async_write и подобными. На сегодняшний день это самый удобный способ асинхронного ввода-вывода в C++.

Производительность

Возобновление корутины значительно дешевле переключения потоков. Компилятор часто встраивает части автомата состояний. Выполните профилирование, чтобы убедиться, что цепочка ожидаемых объектов компилируется эффективно.

Дальнейшие направления

В C++23 добавлен std::generator и внесены другие улучшения. В C++26 может появиться std::execution с моделью отправителей и получателей — более универсальная асинхронная среда, взаимодействующая с корутинами.

Быстрая проверка

Какие три метода должен иметь тип ожидаемого объекта?

Итоги

Асинхронные задачи сочетают co_await с ожидаемыми объектами, позволяя писать асинхронный код без обратных вызовов. Ожидаемые объекты содержат await_ready, await_suspend и await_resume. Библиотеки, такие как cppcoro и Asio, предоставляют готовые типы задач и ожидаемых объектов.

Часто задаваемые вопросы

Урок «Асинхронные задачи и типы awaiter» бесплатный?

Да — полный текст урока «Асинхронные задачи и типы awaiter» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.

Чему я научусь в уроке «Асинхронные задачи и типы awaiter»?

Составляйте асинхронные задачи с пользовательскими типами awaiter и promise. Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C++ Academy?

Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Асинхронные задачи и типы awaiter»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C++ Academy?

Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Концепции сопрограмм: co_await, co_yield, co_return
  2. Реализация простого генератора
  3. Асинхронные задачи и типы awaiter
  4. Выделение памяти для кадра сопрограммы
← Назад к C++ Academy