boost::asio::asio_handler_is_continuation の効果
asio_handler_is_continuation
の効果がいまいち良く分からなかったので調べてみました.
ある handler について, asio_handler_is_continuation
の結果が true の場合,
処理が以下の様に少し変わります.
- handler はスレッド固有の private queue に一度登録され, 後で全体の queue に登録される.
- private queue から全体の queue に handler を移動した際, handler 待ちの他のスレッドを起こさない.
一つ目の結果により, handler を登録した関数が完了するまで, その handler が実行されることはありません (io_service::dispatch
で登録した場合等は除きます).
二つ目の結果により, 登録した handler を同じスレッドで実行する確率が上昇します.
これらを以下は例で見てみます.
#include <iostream> #include <chrono> #include <thread> #include <boost/asio.hpp> struct my_handler { void operator()() const { std::cout << "my_handler: " << std::this_thread::get_id() << std::endl; } friend auto asio_handler_is_continuation(my_handler* h) -> bool { return h->is_continuation; } bool is_continuation; }; int main(int argc, char* argv[]) { boost::asio::io_service io_service{}; io_service.post([&] { // handler を登録して 1 秒間 sleep io_service.post(my_handler{argc != 1}); std::this_thread::sleep_for(std::chrono::seconds{1}); std::cout << "handler1: " << std::this_thread::get_id() << std::endl; }); auto t1 = std::thread{[&]{ io_service.run(); }}; auto t2 = std::thread{[&]{ io_service.run(); }}; t2.join(); t1.join(); }
asio_handler_is_continuation
の結果が false の場合:
% ./a.out my_handler: 0x10dd9c000 handler1: 0x10dd19000
my_handler
は io_service::post
で登録されると, 登録したスレッドは別のスレッドで即座に実行されています.
asio_handler_is_continuation
の結果が true の場合:
% ./a.out continuation handler1: 0x1040bc000 my_handler: 0x1040bc000
my_handler
を登録した関数は 1 秒間 sleep しているにも関わらず, その関数が終了するまで my_handler
は実行されていません.
また, my_handler
は, それを登録したスレッドと同一のスレッドで呼び出されています.