Ioan Irggq
Ioan Irggq

Reputation: 41

steady timer asio boost

Why doesn't my timer expire after 1 second but waits for 10 seconds?

#include <boost/asio.hpp>
#include <boost/bind.hpp>

#include <iostream>

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

    int count = 0;
    boost::asio::steady_timer t(io, boost::asio::chrono::seconds(10));

    t.async_wait([&t](const boost::system::error_code& ec) {
        t.expires_at(t.expiry() + boost::asio::chrono::seconds(9));
    });

    io.run();
    return 0;
}

Upvotes: 3

Views: 5763

Answers (1)

sehe
sehe

Reputation: 392931

It should take "exactly" 10 seconds: Live On Coliru

boost::asio::steady_timer t(io, boost::asio::chrono::seconds(10));

That's where you set the expiry in relative amount (duration) from now().

The second "instruction":

t.expires_at(t.expiry() + boost::asio::chrono::seconds(9));

Would increase the expiry by another 9 seconds, relative to the original 10s deadline. However, you only give that instruction once the original 10s delay has completed. So it has no effect at all, unless you start another [async_]wait on the timer.


Modernize, Simplify, and Understand!

Instead of deprecated io_service, consider io_context.

Instead of asio::chrono consider std::chrono.

Instead of chrono::seconds consider std::chrono_literals.

Instead of t.expires_at(t.expiry() + duration) consider t.expires_from_now(duration). Of course, beware that this might not mean the same thing depending on how much latency is accrued in completion handlers or whether cancellation is used.

Live On Coliru

#include <boost/asio.hpp>
#include <iostream>
namespace asio = boost::asio;
using boost::system::error_code;

using namespace std::chrono_literals;
auto now = std::chrono::steady_clock::now;

int main() {
    asio::io_service io;
    asio::steady_timer t(io, 1s);
    int count = 0;

    std::function<void(error_code)> handler;

    auto const start = now();
    handler = [&](error_code ec) {
        std::cout << "at " << (now() - start) / 1.0ms
                  << "ms handler: " << ec.message() << '\n';
        if (ec.failed())
            return;

        if (count++ < 10) {
            t.expires_from_now(500ms);
            t.async_wait(handler);
        }
    };

    t.async_wait(handler);

    io.run();
    std::cout << "at " << (now() - start) / 1.0ms << " Done\n";
}

Prints e.g.

at 1000.31ms handler: Success
at 1500.66ms handler: Success
at 2000.82ms handler: Success
at 2500.97ms handler: Success
at 3001.2ms handler: Success
at 3501.43ms handler: Success
at 4001.64ms handler: Success
at 4501.88ms handler: Success
at 5002.12ms handler: Success
at 5502.36ms handler: Success
at 6002.59ms handler: Success
at 6002.66 Done

Upvotes: 4

Related Questions