使用 boost::asio 实现计时器
这是我们在项目中使用的定时器类,女巫项目处理 4Gbit/s 互联网流量(约 3.0-400 万定时器)。计时器适用于最一般的工作。
计时器.h
/*
* Timer
* Licensed under Apache
*
* Author: KaiWen <wenkai1987@gmail.com>
* Date: Apr-16-2013
*
*/
#ifndef TIMER_H
#define TIMER_H
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/unordered_map.hpp>
typedef boost::asio::deadline_timer* timer_ptr;
namespace bs = boost::system;
class timer;
class timer_node;
class tm_callback {
public:
explicit tm_callback(boost::function<void(timer_node&)>& f) : m_f(f)
{
}
void operator()(timer_node& node, const bs::error_code& e) {
if (!e)
m_f(node);
}
private:
boost::function<void(timer_node&)> m_f;
};
class timer_node {
friend class timer;
public:
timer_node() {}
timer_node(timer_ptr p, int ms, boost::function<void(timer_node&)> f) :
m_tptr(p), m_ms(ms), m_callback(f)
{
}
void reset(unsigned int ms = 0, boost::function<void(timer_node&)> f = 0) {
if (ms)
m_tptr->expires_from_now(boost::posix_time::milliseconds(ms));
else
m_tptr->expires_from_now(boost::posix_time::milliseconds(m_ms));
if (f)
m_tptr->async_wait(boost::bind<void>(tm_callback(f), *this, _1));
else
m_tptr->async_wait(boost::bind<void>(tm_callback(m_callback), *this, _1));
}
private:
timer_ptr m_tptr;
int m_ms;
boost::function<void(timer_node&)> m_callback;
};
计时器.cpp
/*
* Timer
*
* Licensed under Apache
*
* Author: KaiWen <wenkai1987@gmail.com>
* Date: Apr-16-2013
*
*/
#include "timer.h"
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
namespace ba = boost::asio;
timer::timer(int thread_num) : m_next_ios(0), m_size(0) {
for (int i = 0; i < thread_num; i++) {
io_service_ptr p(new ba::io_service);
work_ptr pw(new ba::io_service::work(*p));
m_ios_list.push_back(p);
m_works.push_back(pw);
}
pthread_spin_init(&m_lock, 0);
}
timer::~timer() {
pthread_spin_destroy(&m_lock);
}
void timer::run() {
for (size_t i = 0; i < m_ios_list.size(); i++)
m_threads.create_thread(boost::bind(&ba::io_service::run, &*m_ios_list[i]))->detach();
}
如果愿意,可以将 timer.cpp 与 timer.h 结合起来,这样就只有一个头文件了。一个简单的用法:
#include <stdio.h>
#include "timer.h"
timer t(3);
void callback(timer_node& nd) {
std::cout << "time out" << std::endl;
t.del_timer(nd);
}
int main(void) {
t.run();
t.add_timer(5000, callback); // set timeout 5 seconds
sleep(6);
return 0;
}
实现线程专用定时器
上面的计时器有一个锁,导致程序不是很快。你可以实现你的欧文线程特殊定时器,不使用锁,不阻塞,比上面的定时器更胖,但这需要一个“驱动程序”并且很难实现。这是我们实现它的一种方式:
pkt = get_pkt();
if (pkt) {
now = pkt->sec;
timer.execut_timer(now);
}
现在,这里没有锁,并且无阻塞并提高您的性能,我们用它来处理 10GBit/s 的互联网流量(大约 8.0-900 万个计时器)。但这是实现依赖。希望能帮到你。