|  | 
In this tutorial we will modify the program from tutorial Timer.2 so that the timer fires once a second. This will show how to pass additional parameters to your handler function.
#include <functional> #include <iostream> #include <asio.hpp>
        To implement a repeating timer using asio you need to change the timer's
        expiry time in your completion handler, and to then start a new asynchronous
        wait. Obviously this means that the completion handler will need to be able
        to access the timer object. To this end we add two new parameters to the
        print function:
      
at the end of the parameter list.
void print(const std::error_code& /*e*/, asio::steady_timer* t, int* count) {
        As mentioned above, this tutorial program uses a counter to stop running
        when the timer fires for the sixth time. However you will observe that there
        is no explicit call to ask the io_context to stop. Recall that in tutorial
        Timer.2 we learnt that the asio::io_context::run() function completes when
        there is no more "work" to do. By not starting a new asynchronous
        wait on the timer when count
        reaches 5, the io_context will run out of work and stop running.
      
if (*count < 5) { std::cout << *count << std::endl; ++(*count);
Next we move the expiry time for the timer along by one second from the previous expiry time. By calculating the new expiry time relative to the old, we can ensure that the timer does not drift away from the whole-second mark due to any delays in processing the handler.
t->expires_at(t->expiry() + asio::chrono::seconds(1));
        Then we start a new asynchronous wait on the timer. As you can see, the
        std::bind function is used to associate the
        extra parameters with your completion handler. The steady_timer::async_wait()
        function expects a handler function (or function object) with the signature
        void(const std::error_code&). Binding the additional parameters
        converts your print function
        into a function object that matches the signature correctly.
      
        In this example, the asio::placeholders::error argument to std::bind
        is a named placeholder for the error object passed to the handler. When initiating
        the asynchronous operation, and if using std::bind,
        you must specify only the arguments that match the handler's parameter list.
        In tutorial Timer.4 you will see that this placeholder may be elided if the
        parameter is not needed by the completion handler.
      
t->async_wait(std::bind(print, asio::placeholders::error, t, count)); } } int main() { asio::io_context io;
        A new count variable is added
        so that we can stop the program when the timer fires for the sixth time.
      
int count = 0; asio::steady_timer t(io, asio::chrono::seconds(1));
        As in Step 4, when making the call to steady_timer::async_wait()
        from main we bind the additional
        parameters needed for the print
        function.
      
t.async_wait(std::bind(print, asio::placeholders::error, &t, &count)); io.run();
        Finally, just to prove that the count
        variable was being used in the print
        handler function, we will print out its new value.
      
std::cout << "Final count is " << count << std::endl; return 0; }
See the full source listing
Return to the tutorial index
Previous: Timer.2 - Using a timer asynchronously
Next: Timer.4 - Using a member function as a completion handler