Search code examples
c++boostboost-asio

boost::asio::bind_executor() behavior, is it intended?


I want to run service in one io_context and do bussiness logic in another io_context. But first I want to know more about re-dispatch behavior, so I write some experimental codes. Here is my first version (without using boost::asio::bind_executor())

boost::asio::io_context context1;
boost::asio::io_context context2;

// for simplicity I use post here, it will be socket operation in real code
boost::asio::post(context1, [&context2]()
    { boost::asio::post(context2, []() { printf("job finished"); }); });

// notice I didn't run context1 here
context2.run();

context1 didn't run, in this case no job posted to context2. So context2.run() return immediately. Of course nothing printed on screen.

Then here is the second version using boost::asio::bind_executor()

boost::asio::io_context context1;
boost::asio::io_context context2;

boost::asio::post(context1, boost::asio::bind_executor(context2, []()
    { printf("job finished"); }));

// notice I didn't run context1 here
context2.run();

In this case, process stuck in context2.run() forever, waiting for pending job to be delivered.

So hand written wrapper code and boost::asio::bind_executor() behave different. Is it bug or intended? And which one is suggested way?

Thanks in advance


Solution

  • In the second example, you post the function for execution to context1 (which did not run) but you bind the completion handler to the conext2’s executor. This means that:

    1. context1’s Asynchronous Operation Processor is not executing the function since the context1 didn’t run.
    2. context2’s Asynchronous Event Demultiplexer waits for the event to occur on the completion event queue, and therefore, blocks your completion handler to printf. This is because it is bound to dequeue an event or result from the queue and associate it with the completion handler.

    In the first example, the context2’s post is inside the context1’s completion handler, and since the context1 did not run, the context1’s Asynchronous Operation Processor never executed, and as the result, the context1’s Asynchronous Event Demultiplexer has nothing to wait for. Ergo quick return.

    Boost docs