一. 定时器简介
服务器程序一般需要处理三种时间,分别是:网络I/O事件,信号事件,定时器事件。一个服务器往往需要同时管理多个定时事件,所以需要一个数据结构有效的管理定时事件,以实现对于定时事件的统一管理。
二. 定时器通用接口
一般来说,定时器都需要以下接口方便对于定时器的管理。
同时,定时器节点中的元素至少有超时时间和超时要执行的回调函数。
三. 链表定时器的实现
//
// Created by Administrator on 2022/4/28 0028.
//
#ifndef TIMER_LIST_TIMER_H
#define TIMER_LIST_TIMER_H
#include <ctime>
typedef void (*callback)(void *arg);
struct user_data {
int number;
};
typedef struct node {
int expire; // 超时时间
callback cb; // 回调函数
void *data; // 传入回调函数数据
node *pre; // 前一个指针
node *next; // 后一个指针
node(int expire, callback cb, void *arg) {
this->expire = expire;
this->cb = cb;
this->data = arg;
pre = nullptr;
next = nullptr;
}
}node;
class list_timer {
private:
node *head;
node *tail;
void add_timer(node *node, struct node *list);
public:
// 定时器初始化
list_timer();
// 定时器销毁
~list_timer();
// 添加定时器
void add_timer(node *node);
// 调整定时器
void adjust_timer(node *node);
// 删除定时器
void delete_timer(node *node);
// 更新定时器
void upgrade_timer();
// 查找最近的定时器
node *find_nearest_node();
};
#endif //TIMER_LIST_TIMER_H
//
// Created by Administrator on 2022/4/28 0028.
//
#include "List_Timer.h"
list_timer::list_timer() {
head = tail = nullptr;
}
list_timer::~list_timer() {
node *temp = head;
while (temp) {
head = head->next;
head->pre = nullptr;
delete temp;
temp = head;
}
}
void list_timer::add_timer(node *node, struct node *list) {
struct node *temp = list;
while (temp && temp->expire < node->expire) {
temp = temp->next;
}
if (!temp) {
tail->next = node;
node->pre = tail;
tail = node;
return;
}
if (temp == head) {
node->next = head;
head->pre = node;
head = node;
return;
}
struct node *pre_node = temp->pre;
pre_node->next = node;
node->pre = pre_node;
node->next = temp;
temp->pre = node;
}
void list_timer::add_timer(node *node) {
if (!node) {
return;
}
if (!head) {
head = tail = node;
} else {
add_timer(node, head);
}
}
void list_timer::adjust_timer(node *node) {
if (!node) {
return;
}
struct node *temp = node->next;
if (!temp || temp->expire > node->expire) {
return;
}
if (node == head) {
head = head->next;
head->pre = nullptr;
node->next = nullptr;
add_timer(node, head);
} else {
node->pre->next = node->next;
node->next->pre = node->pre;
node->pre = node->next = nullptr;
add_timer(node, temp);
}
}
void list_timer::delete_timer(node *node) {
if (node == head && node == tail) {
delete node;
head = tail = nullptr;
return;
}
if (node == head) {
head = head->next;
head->pre = nullptr;
delete node;
return;
}
if (node == tail) {
tail = tail->pre;
tail->next = nullptr;
delete node;
return;
}
node->pre->next = node->next;
node->next->pre = node->pre;
delete node;
}
void list_timer::upgrade_timer() {
if (!head) {
return;
}
time_t cur = time(nullptr);
node *temp = head;
while (temp && temp->expire < cur) {
head = head->next;
if (head) {
head->pre = nullptr;
}
temp->cb(temp->data);
delete temp;
temp = head;
}
}
node *list_timer::find_nearest_node() {
return head;
}