graham.reeds
graham.reeds

Reputation: 16486

steady_timer not firing

I need to be able to test that after an expiry time a function is called. After this failed to work I wrote a small MCE that demonstrates the essentials of the test. It returns without firing the handler.

Uncomment the line below 'is there a handler to expire?' causes it echo 1 to the console which means there is an unexpired handler.

According to the documentation the

The handler will be called when:

  • The timer has expired.
  • The timer was cancelled, in which case the handler is passed the error code boost::asio::error::operation_aborted.

So I think I should at least get 'handler' echoed to the screen when that line is uncommented.

Worryingly if you move it after the sleep_for and yield lines there is still a handler active.

Why isn't my timer firing?

MCE:

#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
#include <iostream>
#include <thread>

void handler(const boost::system::error_code& error)
{
    std::cout << "handler." << std::endl;
    if (!error)
    {
        std::cout << "Timer expired." << std::endl;
    }
}

int main(int argc, char* argv[]) 
{
    boost::asio::io_service io_service;

    // Construct a timer without setting an expiry time.
    boost::asio::steady_timer timer(io_service);

    // expire immediately
    timer.expires_from_now(std::chrono::seconds(0));

    // Wait for the timer to expire.
    timer.async_wait(handler);  

    // is there a handler to expire?
    // std::cout << "Expiry : " << timer.expires_from_now(std::chrono::seconds(1)) << std::endl;

    // added to allow the timer to expire
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::this_thread::yield();
}

Upvotes: 3

Views: 2800

Answers (1)

Mohamad Elghawi
Mohamad Elghawi

Reputation: 2124

Problem

You are using the asynchronous variant of wait without calling io_service.run();

This call is required because operating system-specific functions have to take over control. Remember that it is the I/O service in the I/O service object which implements asynchronous operations based on operating system-specific functions.

Solution

int main(int argc, char* argv[])
{
    boost::asio::io_service io_service;

    // Construct a timer without setting an expiry time.
    boost::asio::steady_timer timer(io_service);

    // expire immediately
    timer.expires_from_now(std::chrono::seconds(0));

    // Wait for the timer to expire.
    timer.async_wait(handler);

    io_service.run();
}

Upvotes: 2

Related Questions