非同期タスクとawaiter型
カスタムawaiter型とpromise型で非同期タスクを組み合わせます。
「非同期タスクと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、中断を省略する場合はtrueawait_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フィードバックを取得できます。ローカル設定は不要です。