Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Boost.Asioにおけるcoroutineの活用法
Search
Takatoshi Kondo
April 19, 2024
Programming
380
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Boost.Asioにおけるcoroutineの活用法
C++20以降で使える、asioとcoroutineの組み合わせかたについて。
特に非同期処理の完了を複数同時待ちする方法について紹介。
Takatoshi Kondo
April 19, 2024
More Decks by Takatoshi Kondo
See All by Takatoshi Kondo
boost::multi_index version >= 1.56.0 internal structure and iteration algorithm for gdb Boost-Prerry-Printer
redboltz
0
370
Other Decks in Programming
See All in Programming
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
410
Strategic Design in the Frontend: Moduliths & Micro Frontends @DDDEurope
manfredsteyer
PRO
0
130
スマートグラスで並列バイブコーディング
hyshu
0
270
AIキャラアプリkaiwaの低遅延音声通話基盤をどう作ったか - AWS Gravitonで支える低遅延・低コストAI Agent基盤
mogamit
0
120
ランチタイムLT会3周年!ランチタイムLT会を3年間続けられたお話
y0hgi
1
110
Semantic Version 単位で戦略を柔軟に変えて、パッケージアップデートを自動化する
daitasu
1
320
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
4.6k
The NotImplementedError Problem in Ruby
koic
1
970
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
14
6.4k
jQueryをバージョンアップする前に使いたいjQuery Migrate
matsuo_atsushi
0
610
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
980
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
2.3k
Featured
See All Featured
The Illustrated Children's Guide to Kubernetes
chrisshort
51
52k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.3k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
400
The browser strikes back
jonoalderson
0
1.3k
Documentation Writing (for coders)
carmenintech
77
5.4k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
200
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
210
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
55k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
240
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.6k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
150
Transcript
Boost.Asioにおける coroutineの活用法 C++20以降で使える、asioとcoroutineの組み合わせ 近藤 貴俊 redboltz
発表者について • 近藤貴俊 redboltz • Boost Libraries コントリビュータ • MQTT
(IoT分野でよく使われる軽量プロトコル) ライブラリ作者 async_mqtt, mqtt_cpp • 軽量シリアライズフォーマット MessagePack の CおよびC++ 版 msgpack-c メンテナ • stackoverflowでQ&A活動中 2/20
Boost.Asioとは? • Asynchronous IO で asio • 非同期処理の基盤となるメカニズムを提供 • 非同期処理の各種応用を提供
• ネットワーク通信 • タイマ • コンソール入出力 • シグナル • etc 3/20
非同期処理の完了を通知する手段 • コールバック • 関数、関数オブジェクト、ラムダ式 など • CompletionToken • use_future,
use_awaibale, deferred, experimental::use_promise など 4/20 本日のメインテーマ asioスタイルの非同期関数の例 ここに何を渡すかで戻り値の型が変わる
callback vs coroutine 5/20 https://godbolt.org/z/MfW5MoTcY https://godbolt.org/z/M7rMe6ren
6/20 coroutine callback VS
co_await 7/20 • 非同期処理の完了を待つことができる • どこで待てるのか 戻り値の型がawaitable<T> の関数の中 co_composedに渡すラムダ式の中
co_await 8/20 • なにを待てるのか 戻り値の型がawaitable<T> の関数呼び出し CompletionTokenとして、use_awaitableを渡した関数呼び出し CompletionTokenとして、deferredを渡した関数呼び出し CompletionTokenとして、use_promiseを渡した関数呼び出し
co_await 9/20 • どこでなにを待てるのか 戻り値の型がawaitable<T> の関数呼び出し CompletionTokenとして、use_awaitableを渡した関数呼び出し CompletionTokenとして、deferredを渡した関数呼び出し CompletionTokenとして、use_promiseを渡した関数呼び出し 戻り値の型がawaitable<T>
の関数の中 全て待てる https://godbolt.org/z/xEd4qWEj3
co_await 10/20 • どこでなにを待てるのか 戻り値の型がawaitable<T> の関数呼び出し CompletionTokenとして、use_awaitableを渡した関数呼び出し CompletionTokenとして、deferredを渡した関数呼び出し CompletionTokenとして、use_promiseを渡した関数呼び出し co_composedに渡すラムダ式の中
awaitable以外 待てる https://godbolt.org/z/dbfhdY7jG
co_composedのうれしさ 11/20 • CompletionTokenベースの関数内で co_awaitが使える • awaitableの連鎖を断ち切ることができる • ただし、co_composed関数の中からawaitableな関数は呼び出せない https://godbolt.org/z/snx1643b4
非awaitable非同期関数 awaitable非同期関数 非awaitable非同期関数 awaitable非同期関数 CompletionTokenBased
co_awaitとマルチウェイト 12/20 • 典型的なマルチウェイトのパターン • 複数の非同期関数を呼び出し、最初の結果が来たら他をキャンセルする • 例:タイムアウト付き受信処理 • 複数の非同期関数を呼び出し、全ての結果がそろってから処理を行う
• 例: メッセージの一斉配信処理 • 待つ要素の種類と数 • コンパイル時に決まっている • 例:1つの受信待ちに1つのタイムアウト • 実行時に決まる • 例:現在接続しているクライアント全員にメッセージ配信し、 全ての非同期送信の結果を待つ • awaitableか非awaitableかで方法が異なる マルチウェイトになっていない例 async_func1()の非同期処理の完了を待ってから async_func2()を開始してしまう 全部待ち ひとつ待ち 静的 動的 awaitable 非awaitable
13/20 https://godbolt.org/z/nxzPoEafz awaitableな非同期関数群のマルチウェイト 今ひとつ釈然としないが、こういう仕様 全部待ち 静的 awaitable co_awaitとマルチウェイト co_await (aaa()
&& bbb())
14/20 https://godbolt.org/z/5rb34T38Y co_awaitとマルチウェイト co_await (aaa() || bbb()) ひとつ待ち 静的 awaitable
15/20 https://godbolt.org/z/1Tx4rE75n co_awaitとマルチウェイト make_parallel_group(funcs...) wait_for_all() 全部待ち 静的 非awaitable
16/20 https://godbolt.org/z/hn8GMs1We co_awaitとマルチウェイト make_parallel_group(funcs...) wait_for_one() ひとつ待ち 静的 非awaitable
17/20 https://godbolt.org/z/c6ao6883c co_awaitとマルチウェイト make_parallel_group(vec) wait_for_all() 全部待ち 動的 非awaitable
18/20 https://godbolt.org/z/69zWs7M5G co_awaitとマルチウェイト make_parallel_group(vec) wait_for_one() ひとつ待ち 動的 非awaitable
co_awaitとマルチウェイト まとめ 19/20 要素数確定タイミング awaitable非同期関数 非awaitable非同期関数 コンパイル時 co_await (... &&
...) co_await (... || ...) co_await make_parallel_group( func1(deferred), func2(experimental::use_promise) ).async_wait( experimental::wait_for_all(), // experimental::wait_for_one(), deferred ); 実行時 調査した限り手段無し using op_type = decltype(post(exe, append(deferred, int{}))); std::vector<op_type> ops; for (int i = 0; i != 5; ++i) ops.push_back(post(exe, append(as::deferred, i*10))); auto [orders, values] = co_await experimental::make_parallel_group( ops ).async_wait( experimental::wait_for_all(), // experimental::wait_for_one(), deferred ); 全部待ち 非awaitable awaitable 静的 動的 ひとつ待ち 全部待ち ひとつ待ち 全部待ち ひとつ待ち
以上。時間があればBonus Slides 20/20
co_spawn • coroutineを起動する 21/20 #include <iostream> #include <boost/asio.hpp> namespace as
= boost::asio; as::awaitable<void> coro_main() { std::cout << "coro started" << std::endl; co_return; } int main() { as::io_context ioc; as::co_spawn( ioc.get_executor(), coro_main, as::detached ); ioc.run(); } ←callableを渡している https://godbolt.org/z/bjE4TrP3v #include <iostream> #include <boost/asio.hpp> namespace as = boost::asio; as::awaitable<void> coro_main() { std::cout << "coro started" << std::endl; co_return; } int main() { as::io_context ioc; as::co_spawn( ioc.get_executor(), coro_main(), as::detached ); ioc.run(); } https://godbolt.org/z/1dTxc66do ←awaitableを渡している
co_spawnの宣言 22/20 https://www.boost.org/doc/libs/1_84_0/doc/html/boost_asio/reference/co_spawn/overload1.html https://www.boost.org/doc/libs/1_84_0/doc/html/boost_asio/reference/co_spawn/overload5.html
CompletionToken指定時の注意 • 第1パラメタがboost::system::error_codeの場合の取り扱い • successのときは何も起こらず、その他errorの時、例外がthrowされる • これを防ぐには、as_tuple(deferred)のように、as_tupleで囲む こうすれば、successであってもerrorであっても、tupleの0番目の 要素として、 boost::system::error_codeが取得できる
23/20
CompletionToken指定時の戻り値の型 24/20 boost::asio::awaitable< void, boost::asio::any_io_executor > boost::asio::awaitable< void, boost::asio::any_io_executor >
boost::asio::deferred_async_operation< void (), boost::asio::detail::initiate_dispatch > boost::asio::experimental::promise< void (), boost::asio::basic_system_executor< boost::asio::execution::detail::blocking::possibly_t<0>, boost::asio::execution::detail::relationship::fork_t<0>, std::allocator<void> >, std::allocator<void> > https://godbolt.org/z/W9veEY35v boost::typeindex::type_id< decltype(as::post(as::deferred)) >().pretty_name() この部分を差し替えて出力
co_composedとexecutor 25/20 • co_composedがどのexecutorで動いているのか https://godbolt.org/z/vs9cGdEeK