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
0
320
Boost.Asioにおけるcoroutineの活用法
C++20以降で使える、asioとcoroutineの組み合わせかたについて。
特に非同期処理の完了を複数同時待ちする方法について紹介。
Takatoshi Kondo
April 19, 2024
Tweet
Share
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
360
Other Decks in Programming
See All in Programming
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
700
技術検証結果の整理と解析をAIに任せよう!
keisukeikeda
0
130
Angular-Apps smarter machen mit Gen AI: Lokal und offlinefähig - Hands-on Workshop!
christianliebel
PRO
0
120
AIコードレビューの導入・運用と AI駆動開発における「AI4QA」の取り組みについて
hagevvashi
0
500
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
770
ふつうのRubyist、ちいさなデバイス、大きな一年 / Ordinary Rubyists, Tiny Devices, Big Year
chobishiba
1
480
CS教育のDX AIによる育成の効率化
niftycorp
PRO
0
140
maplibre-gl-layers - 地図に移動体たくさん表示したい
kekyo
PRO
0
300
クライアントワークでSREをするということ。あるいは事業会社におけるSREと同じこと・違うこと
nnaka2992
1
350
Takumiから考えるSecurity_Maturity_Model.pdf
gessy0129
1
150
仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介
orgachem
PRO
6
2.3k
20260313 - Grafana & Friends Taipei #1 - Kubernetes v1.36 的開發雜記:那些困在 Alpha 加護病房太久的 Metrics
tico88612
0
220
Featured
See All Featured
Art, The Web, and Tiny UX
lynnandtonic
304
21k
Google's AI Overviews - The New Search
badams
0
930
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
770
Facilitating Awesome Meetings
lara
57
6.8k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
230
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.6k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.8k
Are puppies a ranking factor?
jonoalderson
1
3.1k
Designing for Performance
lara
611
70k
BBQ
matthewcrist
89
10k
Making the Leap to Tech Lead
cromwellryan
135
9.8k
SEO for Brand Visibility & Recognition
aleyda
0
4.4k
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