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

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

相关文章

51单片机学习记录———定时器

文章目录 前言一、定时器介绍二、STC89C52定时器资源三、定时器框图四、定时器模式五、定时器相关寄存器六、定时器练习 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出~ 提示:以下是本篇文章正文内容,下面案例可供参考 一、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 定时器作用: 1.用于计数系统,可

问题:第一次世界大战的起止时间是 #其他#学习方法#微信

问题:第一次世界大战的起止时间是 A.1913 ~1918 年 B.1913 ~1918 年 C.1914 ~1918 年 D.1914 ~1919 年 参考答案如图所示

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

java中查看函数运行时间和cpu运行时间

android开发调查性能问题中有一个现象,函数的运行时间远低于cpu执行时间,因为函数运行期间线程可能包含等待操作。native层可以查看实际的cpu执行时间和函数执行时间。在java中如何实现? 借助AI得到了答案 import java.lang.management.ManagementFactory;import java.lang.management.Threa

时间服务器中,适用于国内的 NTP 服务器地址,可用于时间同步或 Android 加速 GPS 定位

NTP 是什么?   NTP 是网络时间协议(Network Time Protocol),它用来同步网络设备【如计算机、手机】的时间的协议。 NTP 实现什么目的?   目的很简单,就是为了提供准确时间。因为我们的手表、设备等,经常会时间跑着跑着就有误差,或快或慢的少几秒,时间长了甚至误差过分钟。 NTP 服务器列表 最常见、熟知的就是 www.pool.ntp.org/zo

20170723 做的事 ecdsa的签名验证时间短于bls signature

1 今天在虚拟机 /home/smile/Desktop/20170610/Test//time_ecdsa 文件夹下,找到ecdsa的验证时间是 989.060606μs μs 先 make ,然后run。 再取BLS的签名生成时间: ./run  2  gnuplot 画图,画对比的时间 gnuplot 画图参考教程 http://blog.sciencen

GaussDB关键技术原理:高性能(二)

GaussDB关键技术原理:高性能(一)从数据库性能优化系统概述对GaussDB的高性能技术进行了解读,本篇将从查询处理综述方面继续分享GaussDB的高性能技术的精彩内容。 2 查询处理综述 内容概要:本章节介绍查询端到端处理的执行流程,首先让读者对查询在数据库内部如何执行有一个初步的认识,充分理解查询处理各阶段主要瓶颈点以及对应的解决方案,本章以GaussDB为例讲解查询执行的几个主要阶段

Python几种建表方法运行时间的比较

建立一个表[0,1,2,3.......10n],下面几种方法都能实现,但是运行时间却截然不同哦 import time#方法一def test1(n):list=[]for i in range(n*10):list=list+[i]return list#方法二def test2(n):list=[]for i in range(n*10):list.append(i)#方法三d

又看见定时器了,怎么这么想写了~~

1.scheduleUpdate(); 与virtual void update(float dt);   联合使用,就是每隔一段时间就调用一次update,实际上是每一帧都调用一次updata方法,scheduleUpdate();方法相当于开启了定时器。 2.schedule的作用和scheduleUpdate差不多,只是这个其实更好用一些,这个可以只是指定调用的方法,系统默认每一帧都调用一

高性能并行计算华为云实验五:

目录 一、实验目的 二、实验说明 三、实验过程 3.1 创建PageRank源码 3.2 makefile的创建和编译 3.3 主机配置文件建立与运行监测 四、实验结果与分析 4.1 采用默认的节点数量及迭代次数进行测试 4.2 分析并行化下节点数量与耗时的变化规律 4.3 分析迭代次数与耗时的变化规律 五、实验思考与总结 5.1 实验思考 5.2 实验总结 E