В этом руководстве мы изменим программу с учебника Timer.2, чтобы таймер работал один раз в секунду. Это покажет, как передать дополнительные параметры функции обработчика.
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
Для реализации повторяющегося таймера с использованием азио необходимо изменить время истечения таймера в функции обратного вызова, а затем начать новое асинхронное ожидание. Очевидно, это означает, что функция обратного вызова должна иметь доступ к объекту таймера. Для этого мы добавляем в функцию<print
>два новых параметра:
- Указатель на объект таймера.
- Счетчик, чтобы мы могли остановить программу, когда таймер выстрелит в шестой раз.
void print(const boost::system::error_code& ,
boost::asio::deadline_timer* t, int* count)
{
Как упоминалось выше, эта учебная программа использует счетчик, чтобы прекратить работу, когда таймер загорается в шестой раз. Однако вы заметите, что нет явного вызова, чтобы попросить io_service остановиться. Напомним, что в учебнике Timer.2 мы узнали, чтоio_service::run()Функция завершается, когда больше нет «работы». Не начав новое асинхронное ожидание на таймере, когда<count
>достигнет 5, сервис io_ перестанет работать.
if (*count < 5)
{
std::cout << *count << std::endl;
++(*count);
Затем мы перемещаем время истечения для таймера на одну секунду от предыдущего времени истечения. Вычисляя новое время истечения по отношению к старому, мы можем гарантировать, что таймер не отходит от целой секунды из-за каких-либо задержек в обработке обработчика.
t->expires_at(t->expires_at() + boost::posix_time::seconds(1));
Затем мы начинаем новое асинхронное ожидание на таймере. Как видите, функция boost::bind() используется для связи дополнительных параметров с обработчиком обратного вызова.deadline_timer::async_wait()функция ожидает функцию обработчика (или объект функции) с подписью<void(constboost::system::error_code&)
>. Привязка дополнительных параметров преобразует вашу функцию<print
>в объект функции, который правильно соответствует сигнатуре.
См. также. Обязательная документациядля получения дополнительной информации о том, как использовать усилитель::bind().
В этом примере усилитель::asio::placeholders::error argument to boost::bind() является названным заполнителем для объекта ошибки, переданного обработчику. При запуске асинхронной операции и при использовании бустера::bind() необходимо указать только те аргументы, которые соответствуют списку параметров обработчика. В учебнике Timer.4 вы увидите, что этот заполнитель может ускользать, если этот параметр не нужен обработчику обратного вызова.
t->async_wait(boost::bind(print,
boost::asio::placeholders::error, t, count));
}
}
int main()
{
boost::asio::io_service io;
Добавлена новая переменная<count
>, чтобы мы могли остановить программу, когда таймер загорится в шестой раз.
int count = 0;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));
Как и на шаге 4, при вызовеdeadline_timer::async_wait()из<main
>мы связываем дополнительные параметры, необходимые для функции<print
>.
t.async_wait(boost::bind(print,
boost::asio::placeholders::error, &t, &count));
io.run();
Наконец, чтобы доказать, что переменная<count
>использовалась в функции обработчика<print
>, мы распечатаем ее новое значение.
std::cout << "Final count is " << count << std::endl;
return 0;
}
Полный список источников
Вернуться вучебный индекс
Предыдущая статья:Таймер.2 — Использование таймера асинхронно
Таймер.4 - Использование функции члена в качестве обработчика