Search code examples
c++boostboost-asio

boost.asio using io_context.poll_one to perform a single task that may get suspended


My application spawns boost.asio job, which at some point, execute background task and get suspended.

I'm running this job using io_context_ with the method poll_one. However, once it gets suspended I don't see the rest of the job being executed...

Is this expected ? Do suspended jobs, go out of the queue and re-inserted again as a new jobs, which require additional poll_one to complete ?

For example, am I expected to see the second print message in this program.

boost::asio::spawn(io_context_, [](const boost::asio::yield_context &yield) { 
   print("do stuff"); 
   io_task(yield);
   print("do more stuff");
}

io_context_.poll_one(); 

Thanks


Solution

  • Is this expected ? Do suspended jobs, go out of the queue and re-inserted again as a new jobs, which require additional poll_one to complete ?

    Yes.

    Moreover many async operations are actually composed operations, which by definition consist of multiple (potentially unbounded) steps that will post new intermediate handlers until the final completion.

    Moreover, awaitables may not be eager (i.e. use initial_suspend to suspend) making any C++20 coro into a composed operation in this respect.

    spawn() is never eager (i.e. it is always lazy), in that you can spawn() many stackful coroutines before even starting the execution context and nothing will happen.

    What To Do

    In the general sense, don't rely on implementation details that have no guarantees in the public documentation. The only reason to use poll_one/run_one in my experience is when integrating with an external event loop (e.g. How to communicate with child process asynchronously?).

    For some other use-cases where I see people use XXX_one() i'd suggest run_for() or run_until(). If all that is not enough, I suggest using timers as events between different asynchronous processes.