我们知道,在类unix系统中,可以使用setitimer函数来设置一个计时器,让系统周期性的发送SIGALRM信号给进程,通过sigaction函数注册SIGALRM信号的回调函数,就可以使我们的进程周期性的处理特定任务。
上面是典型的C的思考方式,在C++中,当然也可以完全按照上面的思路来完成任务,但是这样的做法有一个很大的局限性:sigaction函数不支持注册类的成员函数,我曾经尝试用std::mem_fun解决这个问题,可能是自己太菜,也可能是没用心去研究,反正就是可耻的失败鸟。这里介绍一个替代方案,将上述产生timer的过程与回调函数的注册封装到一起实现。
首先下载头文件。
里面封装了一个basic_repeating_timer模板类,并且对最常用的模板参数做了typedef处理
typedef basic_repeating_timer<boost::posix_time::ptime> repeating_timer;
该模板类接口基本上看名字就可以理解其作用:
- repeating_timer( io_service ) -构造函数
- void start( repeat_interval, handler ) - 启动计时器,设置重复时间以及相应的回调函数
- void stop(), void cancel() -停止/取消计时器
- void change_interval( repeat_interval ) - 更改重复时间
该模板类的作者写了一个例子,原文参见
我把里面的example函数改成main函数后,得到源文件如下:
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <boost/ptr_container/ptr_array.hpp>
#include "basic_repeating_timer.h"
// callback hander for out timers
void handle_timeout( int id, boost::system::error_code const& error )
{
std::cout << "timer " << id << " fired\n";
}
int main()
{
// example shows io_service running in multiple thread, with multiple timers
boost::thread_group threads;
boost::asio::io_service my_io_service;
boost::ptr_array<boost::asio::repeating_timer,10> timers;
// create timers
for( size_t i = 0; i < timers.size(); ++i )
{
timers.replace( i, new boost::asio::repeating_timer(my_io_service) );
}
// start them with their callbacks referencing the next timer
for( size_t i = 0; i < timers.size(); ++i )
{
timers[i].start( boost::posix_time::seconds(i+1),
boost::bind( &handle_timeout,
i,
boost::asio::placeholders::error ) );
}
std::cout << "Press enter to stop the timers...\n";
// finally we start the service running. If the service has nothing to work
// with it will exit immediately.
for( size_t i = 0; i < 5; ++i )
{
threads.create_thread( boost::bind(&boost::asio::io_service::run, &my_io_service) );
}
// wait for the enter/return key to be pressed
std::cin.get();
// explicitly cancel the timers
// could just call timers.release() which would destroy the timer objects but
// for completeness I wanted to show the cancel.
for( size_t i = 0; i < timers.size(); ++i )
{
timers[i].cancel();
}
// and then wait for all threads to complete
threads.join_all();
return 0;
}
|
将上述文件保存为main.cc,编译运行:
$ c++ -lboost_thread -lboost_system main.cc
$ ./a.out
Press enter to stop the timers...
timer 0 fired
timer 0 fired
timer 1 fired
timer 2 fired
为了验证该repeating_timer类能将成员函数注册为回调函数,我对其进行了简单的修改: #include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <boost/ptr_container/ptr_array.hpp>
#include "basic_repeating_timer.h"
class handler{
public:
void handle_timeout( int id, boost::system::error_code const& error );
};
// callback hander for out timers
void handler::handle_timeout( int id, boost::system::error_code const& error )
{
std::cout << "timer " << id << " fired\n";
}
int main()
{
// example shows io_service running in multiple thread, with multiple timers
boost::thread_group threads;
boost::asio::io_service my_io_service;
boost::ptr_array<boost::asio::repeating_timer,10> timers;
handler han;
// create timers
for( size_t i = 0; i < timers.size(); ++i )
{
timers.replace( i, new boost::asio::repeating_timer(my_io_service) );
}
// start them with their callbacks referencing the next timer
for( size_t i = 0; i < timers.size(); ++i )
{
timers[i].start( boost::posix_time::seconds(i+1),
boost::bind( &handler::handle_timeout,
han,
i,
boost::asio::placeholders::error ) );
}
std::cout << "Press enter to stop the timers...\n";
// finally we start the service running. If the service has nothing to work
// with it will exit immediately.
for( size_t i = 0; i < 5; ++i )
{
threads.create_thread( boost::bind(&boost::asio::io_service::run, &my_io_service) );
}
// wait for the enter/return key to be pressed
std::cin.get();
// explicitly cancel the timers
// could just call timers.release() which would destroy the timer objects but
// for completeness I wanted to show the cancel.
for( size_t i = 0; i < timers.size(); ++i )
{
timers[i].cancel();
}
// and then wait for all threads to complete
threads.join_all();
return 0;
}
|
改动主要有两处,一是定义了一个handler类,并将handle_timeout置为其成员函数,二是在调用timers.start()函数是,第二个参数做了相应的修改,这里的修改是参照boost中文文档做的,其实我对这个bind基本没什么理解,照猫画虎而已,修改后编译运行:
$ c++ -lboost_thread -lboost_system memFun.cc -o memfun
$ ./memfun
Press enter to stop the timers...
timer 0 fired
timer 0 fired
timer 1 fired
timer 2 fired
事实证明,我这个虎画的还挺像那么回事^_^
阅读(1929) | 评论(0) | 转发(0) |