定时器是asio库中最简单的一个IO模型,提供等候时间终止的功能。
定时器功能的主要类是:deadline_timer
类,类摘要如下
使用定时器时的头文件:
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::asio;
1. 同步定时器
//同步定时器的用法
void synchronously_timer_test()
{
std::cout << "wait for 5 seconds" << std::endl;
boost::asio::io_service ios; //所有asio程序必须有一个io_service对象
boost::asio::deadline_timer t(ios, boost::posix_time::seconds(15)); //定时器对象构造
std::cout << t.expires_at() << std::endl; //查看终止的绝对时间
t.wait(); //同步等待,如果不等待,则直接往下执行
std::cout << "hello asio" << std::endl;
}
同步定时器和sleep()函数比较
1. thread库中的sleep()使用互斥量和条件变量,在线程中等待。
2. asio则是调用了操作系统的异步机制,如select、epoll等完成。
2. 异步定时器
异步定时器,增加了回调函数,并使用io_service::run()和定时器的async_wait()方法。
回调函数:asio库要求回调函数只能有一个参数,而且这个参数必须是const asio::error_code &
类型。(async_wait()接受的回调函数类型是固定的)
实例:
//回调函数
void printing(system::error_code& e)
{
std::cout << "asynchronously timer test: hello asio" << std::endl;
}
//异步定时器的用法
void asynchronously_timer_test()
{
std::cout << "asychronously timer test begin" << std::endl;
boost::asio::io_service ios; //io_service对象
boost::asio::deadline_timer t(ios, boost::posix_time::seconds(2)); //定时器对象
t.async_wait(printing); //异步等待,传入回调函数,立即返回
ios.run(); //异步IO必须
}
异步定时器区别于同步定时器:
1. async_wait()方法:通知 io_service 异步地执行 IO 操作,并注册回调函数,用于在IO操作完成时由事件多路分离器分派返回值(error_code)调用。
2. 最后必须调用io_service的run()成员函数,它启动前摄器的事件处理循环,阻塞等待所有的操作完成并分派事件。
如果不调用run(),那么虽然操作被异步执行了,但没有一个等待它完成的机制,回调函数将得不到执行机会。
3. 当定时器时间终止时,io_service将调用被注册的printing()回调函数,然后程序结束。
3. 异步定时器使用bind
async_wait()接受的回调函数类型是固定的,如果需要增减回调函数的参数,必须使用bind库来绑定参数以适配它的接口。
实例:
//带参数的回调函数
void printing(std::string &str)
{
std::cout << "asynchronously timer test: hello asio" << std::endl;
std::cout << str << std::endl;
}
//异步定时器的用法
void asynchronously_timer_test()
{
std::cout << "asychronously timer test begin" << std::endl;
boost::asio::io_service ios;
boost::asio::deadline_timer t(ios, boost::posix_time::seconds(2));
std::string str("hello bind");
t.async_wait(boost::bind(printing,boost::ref(str))); //绑定参数,返回一个可用回调函数。
ios.run();
}
4. 多线程中使用同步定时器 实例
//多线程中使用同步定时器
class printer
{
public:
printer(boost::asio::io_service &io):m_strand(io),
m_timer1(io,boost::posix_time::seconds(1)),
m_timer2(io,boost::posix_time::seconds(1)),
m_count(0){
m_timer1.async_wait(boost::bind(&printer::print1, this));
m_timer2.async_wait(boost::bind(&printer::print2, this));
}
void print1(){
boost::mutex::scoped_lock lock(mu);
if (m_count < 10){
std::cout << "timer1:" << m_count << std::endl;
++m_count;
m_timer1.expires_at(m_timer1.expires_at() + boost::posix_time::seconds(1));
m_timer1.async_wait(boost::bind(&printer::print1, this));
}
}
void print2(){
boost::mutex::scoped_lock lock(mu);
if (m_count < 10){
std::cout << "timer2:" << m_count << std::endl;
++m_count;
m_timer2.expires_at(m_timer2.expires_at() + boost::posix_time::seconds(1));
m_timer2.async_wait(boost::bind(&printer::print2, this));
}
}
private:
boost::asio::io_service::strand m_strand;
boost::asio::deadline_timer m_timer1;
boost::asio::deadline_timer m_timer2;
int m_count;
boost::mutex mu;
};
void synchronously_in_multithread_test()
{
std::cout << "synchronously_in_multithread_test begin: " << std::endl;
boost::asio::io_service io;
printer p(io);
boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
io.run();
t.join();
}