高性能定时器 --- 时间堆

2024-06-22 19:58
文章标签 时间 定时器 高性能

本文主要是介绍高性能定时器 --- 时间堆,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

时间堆
    时间轮给我们的感觉依旧不够精细,因为它是按照时间间隔来执行定时器的。
时间堆的设计思路是:
    将所有定时器中超时时间最小的定时器的超时值作为心博间隔。一旦心博函数被调用,超时时间最小的定时器必然到期,我们就可以准确的处理它。然后,再从剩余的定时器中找出超时时间最小的那个,作为下一次心博时间,这样,就显得较为精准了。

    这里我们采用最小堆处理这个问题。


#ifndef MIN_HEAP_TIMER
#define MIN_HEAP_TIMER#include <stdio.h>
#include <netinet/in.h>
#include <time.h>#define BUF_SIZE 64struct client_date
{struct sockaddr_in     cd_address;int             cd_sockfd;char             cd_buf[BUFF_SIZE];mh_timer*        cd_timer;        //每个连接都拥有的一个定时器
};class heap_timer
{
public:time_t expire;client_date *user_data;time_heap(int delay){expire = time(NULL)+delay;}void (*cb_func)(client_date*);
};class time_heap
{
private:heap_timer **array;            //一个指针数组int capacity;int cur_size;public://第一种构造函数//初始化一个给定大小的空堆time_heap(int cap):capacity(cap),cur_size(0){array = new heap_timer*[cap];if(NULL == array)exit(1);for(int i=0; i<cap; i++)array[i] = NULL;}//第二种构造函数//用已有数组来构造堆time_heap(heap_timer **init_array, int cap, int size):capacity(cap),cur_size(size){if(NULL == init_array || size<cap)exit(1);array = new heap_timer*[cap];if(NULL == array)exit(1);for(int i=0; i<cap; 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--)        //对整个堆进行调整(调整的对象是拥有子节点的所有节点)adjust_down(i);}}//析构函数~time_heap(){for(int i=0; i<cur_size; i++)delete array[i];delete[] array;}//添加目标定时器void add_timer(heap_timer *timer){if(NULL == timer)return;if(cur_size >= capacity)resize();cur_size ++;int s = cur_size;int parent;for(; s>0; s=parent){parent = (s-1)/2;//因为是添加进来的,之前部分是排好的。所以只要跟parent比比,一直往上不断比就可以了if(array[parent]->expire > array[s])array[s] = array[parent];elsebreak;    }array[s] = timer;}//删除目标定时器void void del_timer(heap_timer *timer){if(NULL == timer)return;//这是书上的方法,简单,但是容易导致膨胀(不过这种数据结构一般不会突然删某个,而是删顶部元素的)timer->cb_func = NULL;//复杂点的话就是先得知这个节点下标是哪个,然后让最后一个顶替它,对这个节点进行 adjust_down() 操作}//获取顶部定时器heap_timer *top(){if(!empty())return array[0];return NULL;}//删除顶部定时器void del_top(){if(empty())return;if(array[0]){delete array[0];array[0] = array[--cur_size];adjust_down(array[0]);}}//心搏函数void tick(){heap_timer* tmp = array[0];time_t cur = time(NULL);while(!empty()){if(!tmp)break;if(tmp->expire > cur)break;if(tmp->cb_func)tmp->cb_func(tmp->user_data);del_top();tmp = array[0];}}bool empty(){return cur_size==0;}//调整函数(向下)void adjust_down(int s){heap_timer *tmp = array[s];int child;//for循环的条件是: 至少s的左子节点存在(比如s为0,至少孩子节点1要存在,才需要调整,否则没有子节点是不需要调整的)for(; s*2+1<=cur_size-1; ){child = s*2+1;//第一个条件满足说明s的右子节点也存在//第二个条件说明s的右子节点小于左子节点,从而代替左子节点和s节点进行比较if((child<cur_size-1) && (array[child+1]->expire < array[child]->expire))child++;//如果s节点果真大于子节点,那么s节点的位置就要由该子节点来代替//因为有tmp变量指向原s节点,所以这里可以直接覆盖,且接下来要调整的对象就是原s节点现在所处的环境if(tmp->expire > array[child]->expire){array[s] = array[child];s = child;}elsebreak;}array[s] = tmp;}//扩大堆数组的容量void resize(){heap_timer *temp = new heap_timer*[2*capacity];if(NULL == temp)exit(1);for(int i=0; i<2*capacity; i++)temp[i] = NULL;capacity = 2*capacity;for(int i=0; i<cur_size; i++)temp[i] = array[i];delete[] array;array = temp;}
};


这篇关于高性能定时器 --- 时间堆的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1085262

相关文章

Golang如何对cron进行二次封装实现指定时间执行定时任务

《Golang如何对cron进行二次封装实现指定时间执行定时任务》:本文主要介绍Golang如何对cron进行二次封装实现指定时间执行定时任务问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录背景cron库下载代码示例【1】结构体定义【2】定时任务开启【3】使用示例【4】控制台输出总结背景

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

利用Python实现时间序列动量策略

《利用Python实现时间序列动量策略》时间序列动量策略作为量化交易领域中最为持久且被深入研究的策略类型之一,其核心理念相对简明:对于显示上升趋势的资产建立多头头寸,对于呈现下降趋势的资产建立空头头寸... 目录引言传统策略面临的风险管理挑战波动率调整机制:实现风险标准化策略实施的技术细节波动率调整的战略价

Nginx使用Keepalived部署web集群(高可用高性能负载均衡)实战案例

《Nginx使用Keepalived部署web集群(高可用高性能负载均衡)实战案例》本文介绍Nginx+Keepalived实现Web集群高可用负载均衡的部署与测试,涵盖架构设计、环境配置、健康检查、... 目录前言一、架构设计二、环境准备三、案例部署配置 前端 Keepalived配置 前端 Nginx

Python日期和时间完全指南与实战

《Python日期和时间完全指南与实战》在软件开发领域,‌日期时间处理‌是贯穿系统设计全生命周期的重要基础能力,本文将深入解析Python日期时间的‌七大核心模块‌,通过‌企业级代码案例‌揭示最佳实践... 目录一、背景与核心价值二、核心模块详解与实战2.1 datetime模块四剑客2.2 时区处理黄金法

macOS Sequoia 15.5 发布: 改进邮件和屏幕使用时间功能

《macOSSequoia15.5发布:改进邮件和屏幕使用时间功能》经过常规Beta测试后,新的macOSSequoia15.5现已公开发布,但重要的新功能将被保留到WWDC和... MACOS Sequoia 15.5 正式发布!本次更新为 Mac 用户带来了一系列功能强化、错误修复和安全性提升,进一步增

Pandas进行周期与时间戳转换的方法

《Pandas进行周期与时间戳转换的方法》本教程将深入讲解如何在pandas中使用to_period()和to_timestamp()方法,完成时间戳与周期之间的转换,并结合实际应用场景展示这些方法的... 目录to_period() 时间戳转周期基本操作应用示例to_timestamp() 周期转时间戳基

C#实现高性能Excel百万数据导出优化实战指南

《C#实现高性能Excel百万数据导出优化实战指南》在日常工作中,Excel数据导出是一个常见的需求,然而,当数据量较大时,性能和内存问题往往会成为限制导出效率的瓶颈,下面我们看看C#如何结合EPPl... 目录一、技术方案核心对比二、各方案选型建议三、性能对比数据四、核心代码实现1. MiniExcel

JavaScript时间戳与时间的转化常用方法

《JavaScript时间戳与时间的转化常用方法》在JavaScript中,时间戳(Timestamp)通常指Unix时间戳,即从1970年1月1日00:00:00UTC到某个时间点经过的毫秒数,下面... 目录1. 获取当前时间戳2. 时间戳 → 时间对象3. 时间戳php → 格式化字符串4. 时间字符