c++boostasio

boost asio single threaded post() doesn't post when poll() is used?


Everything is handle in a single thread

void GameClient::test()
{
   std::cout <<"called test" << std::endl;
    m_io_context.post([](){
        std::cout << "test" << std::endl;
    });
}

void GameClient::calledFromALoop()
{
    // Use poll instead of run to avoid blocking
    auto count = m_io_context.poll();
    std::cout << "polled: " << count << std::endl;
}

I want every async task to be handled in calledFromALoop() function. It is called from a loop around 50 times per second.

This is the output:

...
polled: 0
polled: 0
polled: 0
called test
polled: 0
polled: 0
polled: 0
...

Can you help me understand why the lambda in post isn't executed ? This is a minimal example, originally in the test function, I use async_resolve, but I have the same behavior.

I don't want to use run() because I don't want calledFromALoop() to block.

But then I don't really understand when the async function is executed (not the handler). For example I assume async_resolve need some work to set up the resolution, then some time to perform network operation, then the handler (callback). When do these steps are executed ?
I think the set up is done at the call of async_resolve, then network time, then the callback is called from poll(). Am I right ?
Using run() instead of poll() will block during the network time.

The weird behavior is if I change the position of this line auto count = m_io_context.poll(); like this:

void GameClient::test()
{
   std::cout <<"called test" << std::endl;
    m_io_context.post([](){
        std::cout << "test" << std::endl;
    });
    m_io_context.poll();
}

void GameClient::calledFromALoop()
{
    
}

I have called test test as expected !


Solution

  • Sure it does:

    Live On Coliru

    #include <boost/asio.hpp>
    #include <iostream>
    namespace asio = boost::asio;
    
    int main() {
        asio::io_context ioc(1);
    
        post(ioc, [] { std::cout << "Hello, world!" << std::endl; });
    
        ioc.poll();
    }
    

    Prints

    Hello, world!
    

    Running Out Of Work

    Like others commented, you might let the service run out of work. You must prevent that or reset() it.

    asio::io_context ioc(1);
    
    post(ioc, [] { std::cout << "Hello, world!" << std::endl; });
    ioc.poll();
    
    post(ioc, [] { std::cout << "Hello, world!" << std::endl; });
    ioc.poll(); // doesn't print anything
    

    However, e.g.:

    auto work = make_work_guard(ioc);
    
    post(ioc, [] { std::cout << "Hello, world!" << std::endl; });
    ioc.poll();
    
    post(ioc, [] { std::cout << "Hello, world!" << std::endl; });
    ioc.poll(); // prints!