基于时间堆的定时器

#ifndef MIN_HEAP
#define MIN_HEAP

#include <iostream>
#include <netinet/in.h>
#include <time.h>
using std::exception;

#define BUFFER_SIZE 64

class heap_timer;
struct client_data {
    sockaddr_in address;
    int sockfd;
    char buf[BUFFER_SIZE];
    heap_timer* timer;
};

class heap_timer {
    public:
        heap_timer(int delay) {
            expire = timer(NULL) + delay;
        }

        time_t expire;
        void (*cb_func)(client_data*);
        client_data* user_data;
};

class time_heap {
    public:
        time_heap(int cap) throw (std::exception) : capacity(cap), cur_size(0) {
            array = new heap_timer* [capacity];
            if (!array) {
                throw std:exception();
            }
            for (int i = 0; i < capacity; ++i) {
                array[i] = NULL;
            }
        }

        time_heap(heap_timer** init_array, int size, int capacity) throw (std::exception) : cur_size(size), capacity(capacity) {
            if (capacity < size) {
                throw std::exception();
            }
            array = new heap_timer* [capacity];
            if (!array) {
                throw std::exception();
            }
            for (int i = 0; i < capacity; ++i) {
                array[i] = NULL;
            }
            if (size != 0) {
                for (int i = 0; i < size; ++i) {
                    array[i] = init_array[i];
                }
                for (int i = (cur_size - 1) / 2; i >= 0; --i) {
                    percolate_down(i);
                }
            }
        }

        ~time_heap() {
            for (int i = 0; i < cur_size; ++i) {
                delete array[i];
            }
            delete[] array;
        }

        void add_timer(heap_timer* timer) throw (std::exception) {
            if (!timer) {
                return;
            }
            if (cur_size >= capacity) {
                resize();
            }
            int hole = cur_size++;
            int parent = 0;
            for (; hole > 0; hole = parent) { // 上滤
                parent = (hole - 1) / 2;
                if (array[parent]->expire <= timer->expire) {
                    break;
                }
                array[hole] = array[parent];
            }
            array[hole] = timer;
        }

        void del_timer(heap_timer* timer) {
            if (!timer) {
                return;
            }
            timer->cb_func = NULL; // 所谓的延迟销毁,节省真正删除该定时器造成的开销,缺点是容易使数组膨胀
        }

        heap_timer* top() const {
            if (empty()) {
                return NULL;
            }
            return array[0];
        }

        void pop_timer() {
            if (empty()) {
                return;
            }
            if (array[0]) {
                delete array[0];
                array[0] = array[--cur_size];
                percolate_down(0);
            }
        }

        void tick() { // 把所有到期的事件都处理掉
            heap_timer* tmp = array[0];
            time_t cur = timer(NULL);
            while (!empty()) {
                if (!tmp) {
                    break;
                }
                if (tmp->expire > cur) {
                    break;
                }
                if (array[0]->cb_func) {
                    array[0]->cb_func(array[0]->user_data);
                }
                pop_timer();
                tmp = array[0];
            }
        }

        bool empty() const {
            return cur_size == 0;
        }

    private:
        void percolate_down(int hole) {
            heap_timer* temp = array[hole];
            int child = 0;
            for (; ((hole * 2 + 1) <= (cur_size - 1)); hole = child) {
                child = hole * 2 + 1;
                if ((child < (cur_size - 1)) && (array[child + 1]->expire < array[child]->expire)) { // 右孩子比左孩子小,换右孩子
                    ++child;
                }
                if (array[child]->expire < temp->expire) { // 交换操作
                    array[hole] = array[child];
                } else {
                    break;
                }
            }
            array[hole] = temp;
        }

        void resize() throw (std::exception) {
            heap_timer** temp = new heap_timer* [2 * capacity];
            for (int i = 0; i < 2 * capacity; ++i) {
                temp[i] = NULL;
            }
            if (!temp) {
                throw std::exception();
            }
            capacity = 2 * capacity;
            for (int i = 0; i < cur_size; ++i) {
                temp[i] = array[i];
            }
            delete[] array;
            array = temp;
        }

        heap_timer** array;
        int capacity;
        int cur_size;
}

#endif

堆是一种高效的数据结构,不熟悉堆的同学先学习下堆。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上图来自Linux高性能服务器编程——游双P211P_{211}P211

添加一个定时器的时间复杂度为O(log2n)O(log_2n)O(log2n),删除定时器复杂度为O(1)O(1)O(1),执行一个定时器时间复杂度为O(1)O(1)O(1)

reference:Linux高性能服务器编程——游双

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值