【Boost】boost库中timer定时器 1
博客转载自:http://blog.csdn.net/liujiayu2/article/details/50384537
同步Timer
asio中提供的timer名为deadline_timer,它提供了超时计时的功能。首先以一个最简单的同步Timer为例来演示如何使用它。
#include <iostream> #include <boost/asio.hpp> int main() { boost::asio::io_service io; boost::asio::deadline_timer timer(io, boost::posix_time::seconds(3)); timer.wait(); std::cout << "Hello, world!\n"; return 0; }
首先常见了一个io_service对象,它提供了IO调度功能,asio库中的所有io操作都是基于它来执行的。然后创建了一个deadline_timer对象,它有两个参数,一个是io_service对象,另一个是超时时间。
创建了timer后,就可以调用wait函数来阻塞等待至timer超时了,它还有一种可以指定错误码的入参的重载形式,关于错误码后面再介绍。
异步Timer
同步timer虽然简单,但由于其会阻塞,在实际的项目中并不常用,而往往使用的是异步timer:指定一个回调函数,计时器超时后执行回调函数。asio中实现异步timer比较简单,示例如下:
void print(const boost::system::error_code& /*e*/) { std::cout << "Hello, world!\n"; } int main() { boost::asio::io_service io; boost::asio::deadline_timer timer(io, boost::posix_time::seconds(5)); timer.async_wait(&print); io.run(); return 0; }
和同步方式相比,它主要有两点不同:
-
调用的是非阻塞函数async_wait,它的入参是一个回调函数。
-
显式调用io_service.run()函数驱动异步IO调度。
取消Timer
void print(const boost::system::error_code& err) { if(err) { std::cout << "timer is canceled\n"; return; } std::cout << "Hello, world!\n"; } int main() { boost::asio::io_service io; boost::asio::deadline_timer timer(io, boost::posix_time::seconds(5)); timer.async_wait(&print); boost::asio::deadline_timer timer2(io, boost::posix_time::seconds(2)); timer2.wait(); timer.cancel(); io.run(); return 0; }
更改Timer超时时间
可以通过expires_from_now和expires_at两个函数更改Timer的超时时间,如下示例就通过它实现一个周期计时器。
Timer还有一种常用操作是取消Timer,基本方法如下:
-
调用timer的cancel函数取消timer
-
timer取消后,回调函数会立即执行,通过err_code可以感知到计时器是否已经被取消
typedef std::function<void (const boost::system::error_code&)> timer_callback ; void print(const boost::system::error_code&) { std::cout << "Hello, world!\n"; } int main() { boost::asio::io_service io; boost::asio::deadline_timer timer(io, boost::posix_time::seconds(1)); timer_callback callback = [&](const boost::system::error_code& err) { print(err); timer.expires_at(timer.expires_at() + boost::posix_time::seconds(1)); timer.async_wait(callback); }; timer.async_wait(callback); io.run(); return 0; }
//
#include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/date_time/posix_time/posix_time.hpp> class printer { public: printer(boost::asio::io_service& io) : timer_(io, boost::posix_time::seconds(1)), count_(0) { timer_.async_wait(boost::bind(&printer::print, this)); } ~printer() { std::cout << "Final count is " << count_ << "\n"; } void print() { if (count_ < 5) { std::cout << count_ << "\n"; ++count_; timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1)); timer_.async_wait(boost::bind(&printer::print, this)); } } private: boost::asio::deadline_timer timer_; int count_; }; int main() { boost::asio::io_service io; printer p(io); io.run(); return 0; }
//
#include <iostream> #include <time.h> #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/function.hpp> #include <boost/date_time/posix_time/posix_time.hpp> using namespace std; //超时控制器类 class TimerController { public: /** * 超时控制器构造函数 * @param ios 异步I/O对象 * @param callbackFunc 超时处理回调函数 * @param uiWaitSec 定时器间隔等待时间,单位:秒 */ explicit TimerController(boost::asio::io_service &ios, boost::function<void()> callbackFunc, unsigned int uiWaitSec) : m_timer(ios, boost::posix_time::seconds(3)) { cout<< "1111111111111" << "-----" << time(NULL)<<endl; m_timeoutHandle = callbackFunc; m_uiWaitSec = uiWaitSec; m_timer.async_wait(boost::bind(&TimerController::onTime, this, boost::asio::placeholders::error)); } /** * 析构函数 */ ~TimerController() { m_timer.cancel(); } /** * 定时器响应函数 * @param error_code 定时器异常错误信息 */ void onTime(const boost::system::error_code&) { m_timeoutHandle(); m_timer.expires_at(m_timer.expires_at() + boost::posix_time::seconds(1)); m_timer.async_wait(boost::bind(&TimerController::onTime, this, boost::asio::placeholders::error)); } private: unsigned int m_uiWaitSec; //定时间间隔等待时间 boost::asio::deadline_timer m_timer; //asio定时器 boost::function<void()> m_timeoutHandle; //超时处理回调函数 }; //构造函数 class CmdQueueManager { public: CmdQueueManager(boost::asio::io_service* io) { m_pTimer = new TimerController(*io,boost::bind(&CmdQueueManager::SendProcess, this),1); } void SendProcess() { cout<< "1111111111111" << "-----" << time(NULL)<<endl; } TimerController * m_pTimer; }; int main() { boost::asio::io_service io; CmdQueueManager t(&io); io.run(); return 0; }
最近做项目时,做了一个定时器,发现定时器回调函数不按照指定时间回调,总是延迟,后经研究发现,是IO出了问题,把一个IO绑定到多个socket上面,并把这个IO绑定到定时器上面,有一些socket连接网络时发出了一些connect行为,这些行为会造成IO阻塞,当然这只是猜测,看到的读者可以帮忙讲解一下。所以本人建议做timer时候,自建一个人“干净”的IO。