web服务器升序链表定时器

#ifndef LST_TIMER
#define LST_TIMER

#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <stdarg.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/uio.h>
#include <time.h>

#define BUFFER_SIZE 64
class util_timer; //声明

//定义用户数据结构体
struct client_data
{
    sockaddr_in address;
    int sockfd;
    char buf[BUFFER_SIZE];
    util_timer *timer;
};

//定时器类
class util_timer
{
public:
    util_timer() : pre(nullptr), next(nullptr) {}

public:
    time_t expire;
    void (*cb_func)(client_data *);
    client_data *user_data;
    util_timer *pre;
    util_timer *next;
};

//定时器链表
class sort_timer_lst
{

private:
    util_timer *head;
    util_timer *tail;

public:
    sort_timer_lst() : head(nullptr), tail(nullptr) {}
    //链表被销毁时,删除所有定时器
    ~sort_timer_lst()
    {
        util_timer *tmp = head;
        while (tmp)
        {
            head = tmp->next;
            delete tmp;
            tmp = head;
        }
    }

    //将目标表定时器添加到链表中
    void add_timer(util_timer *timer)
    {
        if (timer == nullptr)
        {
            return;
        }
        //head头结点为空
        if (head == nullptr)
        {
            head = tail = timer;
            return;
        }
        //如果目标定时器的超时时间小于所有升序链表
        //添加到head节点
        if (timer->expire < head->expire)
        {
            timer->next = head;
            timer->pre = nullptr;
            head->pre = timer;
            head = timer;
            return;
        }
        //否则就进行添加到中间
        add_timer(timer, head);
    }

    //当某个定时事件发生变化时,调整对应的的定时器在链表中的位置
    //只考虑超时时间延长的情况,即往后面移动
    void adjust_timer(util_timer *timer)
    {
        if (timer == nullptr)
        {
            return;
        }
        util_timer *tmp = timer->next;
        //被调整的定时器在尾部
        //或者该定时器的超时值仍然小于下一个
        if (tmp == nullptr || timer->expire < tmp->expire)
        {
            return;
        }

        //如果目标定时器是头结点,则将该定时器取出,再重新插入
        if (timer == head)
        {
            head = head->next;
            head->pre = nullptr;
            timer->next = nullptr;
            //取出,重新插入
            add_timer(timer, head);
        }
        //如果不是头尾节点,在中间
        else
        {
            timer->pre->next = tmp;
            tmp->pre = timer->pre;
            add_timer(timer, timer->next);
        }
    }

    //删除目标定时器
    void del_timer(util_timer *timer)
    {
        if (timer == nullptr)
        {
            return;
        }
        //当链表中只有一个定时器时
        if (timer == head && timer == tail)
        {
            delete timer;
            head = nullptr;
            tail = nullptr;
            return;
        }

        //有多个定时器,并且定时器是链表的尾节点
        //重置尾节点
        if (timer == tail)
        {
            tail = tail->pre;
            tail->next = nullptr;
            delete timer;
            return;
        }

        //是头结点
        if (timer == head)
        {
            head = head->next;
            head->pre = nullptr;
            delete timer;
            return;
        }

        //在中间
        timer->pre->next = timer->next;
        timer->next->pre = timer->pre;
        delete timer;
    }

    //sigalrm信号每次触发就执行一次tick函数
    void tick()
    {
        if (head == nullptr)
        {
            return;
        }
        //获得当前时间
        time_t cur = time(NULL);
        util_timer *tmp = head;
        //从头结点开始依次处理每个定时器,直到遇到一个尚未到期的定时器
        while (tmp)
        {
            //当前时间小于超时时间时
            if (cur < tmp->expire)
            {
                break;
            }

            //否则调用定时器的回调函数,执行任务
            //作用是关闭套接字,从epoll中剔除
            tmp->cb_func(tmp->user_data);
            //执行完定时器中的定时任务后,就将它从链表中剔除,并重置链表头结点
            head = tmp->next;
            //判断此时头结点是否为空
            if (head)
            {
                head->pre = nullptr;
            }
            delete tmp;
            tmp = head;
        }
    }

private:
    //重载辅助函数,设为私有的
    //添加定时器到中间
    void add_timer(util_timer *timer, util_timer *lst_head)
    {
        //双指针方式
        util_timer *prev = lst_head;
        util_timer *tmp = prev->next;
        while (tmp)
        {
            if (timer->expire < tmp->expire)
            {
                prev->next = timer;
                timer->pre = prev;
                timer->next = tmp;
                tmp->pre = timer;
                break;
            }
            prev = tmp;
            tmp = tmp->next;
        }
        //遍历完都没有找到,则说明是最大的
        //将它插到尾部,并设置成tail
        if (tmp == nullptr)
        {
            prev->next = timer;
            timer->pre = prev;
            timer->next = nullptr;
            tail = timer;
        }
    }
};

#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值