timerfd实现多线程定时器

时间:2023-01-15 00:10:22

基本原理

参考了一段别人的代码.修改了更稳健,同时增加单例模式

复用io刷新timerfd
map存申请的fd,key排序,发生的一定是最小的.

代码

timerRunner.cpp

/**
* @file timer_poll.cpp
* @brief
* @author
* @version
* @date 2017-05-05
*/

#include <stdlib.h>
#include "timerRunner.h"
using namespace std;

timer::timer(const timer& ptimer)
{
timer_internal = ptimer.timer_internal;
cb = ptimer.cb;
timer_id = ptimer.timer_id;
repeat = ptimer.repeat;
userdata = ptimer.userdata;
}
timer & timer::operator =(const timer& ptimer)
{
if (this == &ptimer)
{
return *this;
}
timer_internal = ptimer.timer_internal;
cb = ptimer.cb;
timer_id = ptimer.timer_id;
repeat = ptimer.repeat;
userdata = ptimer.userdata;
return *this;
}
int timer::start()
{
struct itimerspec ptime_internal = {0};
ptime_internal.it_value.tv_sec = (int) timer_internal;
ptime_internal.it_value.tv_nsec = (timer_internal - (int) timer_internal)*1000000000;
if(repeat)
{
ptime_internal.it_interval.tv_sec = ptime_internal.it_value.tv_sec;
ptime_internal.it_interval.tv_nsec = ptime_internal.it_value.tv_nsec;
}

timerfd_settime(timer_id, 0, &ptime_internal, NULL);
return 0;
}
int timer::destroy()
{
close(timer_id);
return 0;
}
int timer::timer_modify_internal(double timer_internal)
{
this->timer_internal = timer_internal;
start();
}



int timerRunner::add_timer(timer& ptimer)
{
int timer_id = ptimer.timer_get_id();
struct epoll_event ev;
ev.data.fd = timer_id;
ev.events = EPOLLIN | EPOLLET;
timers_map[timer_id] = ptimer; //add or modify
epoll_ctl (epfd, EPOLL_CTL_ADD, timer_id, &ev);
ptimer.start();

return 0;
}
int timerRunner::del_timer(timer& ptimer)
{
int timer_id = ptimer.timer_get_id();
struct epoll_event ev;
ev.data.fd = timer_id;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl (epfd, EPOLL_CTL_DEL, timer_id, &ev);
timers_map.erase(timer_id);

return 0;
}
int timerRunner::run()
{
char buf[128] ={0};
active = 1;
for (; active ; )
{
struct epoll_event events[MAXFDS] ={0};
int nfds = epoll_wait (epfd, events, MAXFDS, -1);
for (int i = 0; i < nfds; ++i)
{
std::map<int, timer>::iterator itmp = timers_map.find(events[i].data.fd);
if (itmp != timers_map.end())
{
//timer ptimer = itmp->second;
while (read(events[i].data.fd, buf, 128) > 0);
itmp->second.get_user_callback()(itmp->second);
}
}
}
}

pthread_mutex_t timerRunner::mutex = PTHREAD_MUTEX_INITIALIZER;
timerRunner* timerRunner::m_instance = NULL;

timerRunner* timerRunner::getInstance(void)
{
if(NULL == m_instance)
{
pthread_mutex_lock(&mutex);
if(NULL == m_instance)
{
m_instance = new timerRunner(128);
}
pthread_mutex_unlock(&mutex);
}
return m_instance;
}

timerRunner.h

/**
* @file timer_poll.h
* @brief
* @author
* @version
* @date 2017-05-05
*/

#ifndef TIMER_POLL_H
#define TIMER_POLL_H
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/epoll.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <pthread.h>
#include <map>
#define MAXFDS 128
#define EVENTS 100

//#define OWN_TIMTER_EN

class timer;
typedef int (*timer_cb)(timer& ptimer);
class timer
{
public:
timer() : timer_internal(0.0), cb(0), timer_id(0), repeat(0), userdata(0){}
timer(double internal_value, int (*callback)(timer &ptimer), void *data, int rep) : timer_internal(internal_value), cb(callback), userdata(data), repeat(rep)
{
timer_id = timerfd_create(CLOCK_REALTIME, 0);
set_non_block(timer_id);
}
timer(const timer &ptimer);
timer & operator=(const timer &ptimer);
int start();
int destroy();
int timer_modify_internal(double timer_internal);
int timer_get_id()
{
return timer_id;
}
void *timer_get_userdata()
{
return userdata;
}
timer_cb get_user_callback()
{
return cb;
}
~timer()
{
destroy();
}
private:
bool set_non_block (int fd)
{
int flags = fcntl (fd, F_GETFL, 0);
flags |= O_NONBLOCK;
if (-1 == fcntl (fd, F_SETFL, flags))
{
return false;
}
return true;
}
int timer_id;
double timer_internal;
void *userdata;
bool repeat;
timer_cb cb;
} ;

class timerRunner
{
public:
timerRunner(int max_num=128)
{
active = 1;
epfd = epoll_create(max_num);
}
~ timerRunner()
{
}
int add_timer(timer &ptimer);
int del_timer(timer &ptimer);
int run();
int stop()
{
active = 0;
return 0;
}
static timerRunner* getInstance(void);
private:
static pthread_mutex_t mutex;
static timerRunner* m_instance;
int epfd;
int active;
std::map<int, timer> timers_map;
/* data */
} ;
#endif /* TIMER_POLL_H */