liv2hak
liv2hak

Reputation: 14990

boos::asio async_wait seems to be blocking

I was learning boost asio documentation.I came across this deadline_timer example.

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>


/*This timer example shows a timer that fires once every second.*/

void print(const boost::system::error_code& e, boost::asio::deadline_timer* t, int* count)
{
    if (*count < 5)
    {   
        std::cout << *count << std::endl;
        ++(*count);

        t->expires_at(t->expires_at() + boost::posix_time::seconds(1));

        t->async_wait(boost::bind(print,boost::asio::placeholders::error, t, count));
    }   
}

int main()
{
    boost::asio::io_service io; 

    int count = 0;

    boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));

    auto myfunc = boost::bind(print, boost::asio::placeholders::error, &t ,&count);
    t.async_wait(myfunc);

    std::cout << "async wait " << std::endl;

    io.run();

    std::cout << "Just called io.run() " << std::endl;                                                                                                                                                             

    std::cout << "Final count is " << count << std::endl;

    return 0;
}

The async_wait() function seems to be blocking (i.e waiting for the 10 second timer to expire)

The output from the above program is as follows.

async wait 
0
1
2
3
4
Just called io.run() 
Final count is 5

I would expect an async_wait() to create a separate thread and wait for the timer to expire there meanwhile executing the main thread.

i.e I would expect the program to print

Just called io.run() 
Final count is 5

while waiting for the timer to expire.? Is my understanding wrong?

This is my understanding of async_wait(). This implementation looks more like a blocking wait. Is my understanding wrong? What am I missing?

Upvotes: 2

Views: 2086

Answers (2)

Xirema
Xirema

Reputation: 20396

The io.run(); statement is the key to explaining the difference between the output you're getting and the output you're expecting.

In the ASIO framework, any asynchronous commands need to have a dedicated thread to run the callbacks upon. But because ASIO is relatively low-level, it expects you to provide the thread yourself.

As a result, what you're doing when you call io.run(); within the main thread is to specify to the framework that you intend to run all asynchronous commands on the main thread. That's acceptable, but that also means that the program will block on io.run();.

If you intend the commands to run on a separate thread, you'll have to write something like this:

std::thread run_thread([&]() {
    io.run();
});

std::cout << "Just called io.run() " << std::endl;                                                                                                                                                             

std::cout << "Final count is " << count << std::endl;

run_thread.join();

return 0;

Upvotes: 5

David Schwartz
David Schwartz

Reputation: 182769

The async_wait function isn't blocking, run is. That's run's job. If you don't want a thread to block in the io_service's processing loop, don't have that thread call run.

The async_wait function doesn't create any threads. That would make it expensive and make it much harder to control the number of threads servicing the io_service.

Your expectation is unreasonable because returning from main terminates the process. So who or what would wait for the timer?

Upvotes: 2

Related Questions