欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

asio重复调用定时器

程序员文章站 2022-04-03 12:21:22
...

Timer.3 - Binding arguments to a handler

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 <iostream>
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>

To implement a repeating timer using asio you need to change the timer's expiry time in your callback function, and to then start a new asynchronous wait. Obviously this means that the callback function will need to be able to access the timer object. To this end we add two new parameters to the print function:

  • A pointer to a timer object.
  • A counter so that we can stop the program when the timer fires for the sixth time.
void print(const boost::system::error_code& /*e*/,
    boost::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 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() + boost::asio::chrono::seconds(1));

Then we start a new asynchronous wait on the timer. As you can see, the boost::bind() function is used to associate the extra parameters with your callback handler. The steady_timer::async_wait() function expects a handler function (or function object) with the signature void(const boost::system::error_code&). Binding the additional parameters converts your print function into a function object that matches the signature correctly.

See the Boost.Bind documentation for more information on how to use boost::bind().

In this example, the boost::asio::placeholders::error argument to boost::bind() is a named placeholder for the error object passed to the handler. When initiating the asynchronous operation, and if using boost::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 callback handler.

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

int main()
{
  boost::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;
  boost::asio::steady_timer t(io, boost::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(boost::bind(print,
        boost::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;
}
//
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

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

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

    t->expires_at(t->expiry() + boost::asio::chrono::seconds(1));
    t->async_wait(boost::bind(print,
          boost::asio::placeholders::error, t, count));
  }
}

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

  int count = 0;
  boost::asio::steady_timer t(io, boost::asio::chrono::seconds(1));
  t.async_wait(boost::bind(print,
        boost::asio::placeholders::error, &t, &count));

  io.run();

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

  return 0;
}

placeholders::error 占位符

An argument placeholder, for use with boost::bind(), that corresponds to the error argument of a handler for any of the asynchronous functions.

unspecified error;

Requirements

Header: boost/asio/placeholders.hpp

Convenience header: boost/asio.hpp

其它两个参数没有使用占位符,因为其它的两个参数t、count 在异步调用期间,存活周期一直生存。

相关标签: Asio网络库