C++ Academy · レッスン

非同期タスクとawaiter型

カスタムawaiter型とpromise型で非同期タスクを組み合わせます。

レッスン 3/414 ステップ

「非同期タスクとawaiter型」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。

非同期コルーチン

非同期タスクはI/Oで中断し、操作が完了すると再開します。co_awaitを非同期APIと組み合わせることで、コールバックを使わない非同期コードを記述できます。

Task型の概要

Taskは非同期コルーチンをラップします。連鎖にはco_awaitを使用できます。

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

co_awaitの仕組み

コンパイラーがco_await exprを見つけると、exprがawaitableであることを期待します。awaitableには次の3つのメソッドがあります。

  • await_ready() — 中断する場合はfalse、中断を省略する場合はtrue
  • await_suspend(handle) — 中断中に行う処理
  • await_resume() — 呼び出し側のコードに渡す値

awaitableの例:スリープ

遅延後に再開をスケジュールするawaitableです。

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用のawaitable

HTTPリクエスト、タイマー、ファイルI/O向けのawaitableがライブラリから提供されています。同期呼び出しと同じように組み合わせて使用できます。

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

タスクの組み合わせ

あるタスクの内部で別のタスクをawaitすると、タスクが連鎖します。外側のタスクは内側のタスクが完了するまで中断されます。

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

並列タスク

非同期処理を並列に実行するには、各タスクをすぐにはawaitせずに開始し、その後ですべてをawaitします。

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;
}

例外の伝播

非同期タスク内でスローされた例外は、promiseのunhandled_exceptionに保存し、awaiter側で再スローできます。

キャンセル

標準ライブラリには、まだキャンセル用のプリミティブがありません。ライブラリ(cppcoro、boost.cobalt)は、通常、キャンセルトークンやstop sourceを使って独自に構築しています。

Boost.Asioとの統合

Asioはコルーチンをネイティブにサポートしています。async_read、async_writeなどの操作でco_awaitを使用できます。現在のC++における、最も扱いやすい非同期I/Oです。

性能

コルーチンの再開は、スレッドの切り替えよりはるかに低コストです。コンパイラーはステートマシンの一部をインライン化することもあります。awaitableを連ねたコードが適切にコンパイルされるか、プロファイリングで確認してください。

今後の方向性

C++23ではstd::generatorと各種の改善が追加されました。C++26ではstd::execution(sender/receiver)が導入される可能性があります。これはコルーチンと相互運用できる、より汎用的な非同期フレームワークです。

確認問題

awaitable型に必要な3つのメソッドは何ですか?

まとめ

非同期タスクでは、co_awaitとawaitableを組み合わせて、コールバックを使わない非同期コードを記述します。awaitableにはawait_ready、await_suspend、await_resumeがあります。ライブラリ(cppcoro、Asio)が、すぐに使えるタスク型とawaitable型を提供しています。

無料で開始

AI チューターと学ぶ C++ — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
51
レッスン
203

よくある質問

「非同期タスクとawaiter型」レッスンは無料ですか?

はい。「非同期タスクとawaiter型」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。

「非同期タスクとawaiter型」で何を学びますか?

カスタムawaiter型とpromise型で非同期タスクを組み合わせます。 ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C++ Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「非同期タスクとawaiter型」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC++ Academyレッスンでコードを書いて実行できますか?

はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. コルーチンの概念:co_await、co_yield、co_return
  2. シンプルなジェネレーターの実装
  3. 非同期タスクとawaiter型
  4. コルーチンフレームの割り当て
← C++ Academyに戻る