Redis事件管理(二)
Redis的定时器是自己实现的,不是很复杂。说说具体的实现吧。
定时器的存储维护采用的是普通的单向链表结构,具体节点定义为:
/*时间定时器结构体*/
typedef struct aeTimeEvent
{
long long id; /*定时器的编号*/
long when_sec; /* seconds */
long when_ms; /* milliseconds */
aeTimeProc *timeProc;/*时间到达处理函数*/
aeEventFinalizerProc *finalizerProc;/*删除清理函数*/
void *clientData;/*带外数据*/
struct aeTimeEvent *next;/*定时器的存储采用的是链表结构*/
} aeTimeEvent;
定时器记录的根节点的位置是在事件管理器中,剩下的就是普通的操作函数了
/*添加定时器事件,参数为时间控制器,定时时间,处理函数,函数参数,清理函数*/
long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
aeTimeProc *proc, void *clientData,
aeEventFinalizerProc *finalizerProc)
{
/*生成ID*/
long long id = eventLoop->timeEventNextId++;
aeTimeEvent *te; te = zmalloc(sizeof(*te));
if (te == NULL) return AE_ERR;
te->id = id;
/*调整时间*/
aeAddMillisecondsToNow(milliseconds,&te->when_sec,&te->when_ms);
te->timeProc = proc;
te->finalizerProc = finalizerProc;
te->clientData = clientData;
/*加入时间链表中,所有的时间节点都是在头部插入的,没顺序*/
te->next = eventLoop->timeEventHead;
eventLoop->timeEventHead = te;
return id;
}
/*删除时间节点,提供时间点的ID就好,如果没找到就返回错误*/
int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id)
{
aeTimeEvent *te, *prev = NULL; te = eventLoop->timeEventHead;
/*循环查找节点,调用清理函数并释放内存*/
while(te)
{
if (te->id == id)
{
if (prev == NULL)
eventLoop->timeEventHead = te->next;
else
prev->next = te->next;
if (te->finalizerProc)
te->finalizerProc(eventLoop, te->clientData);
zfree(te);
return AE_OK;
}
prev = te;
te = te->next;
}
return AE_ERR; /* NO event with the specified ID found */
}
/*查找激活时间最短的节点*/
static aeTimeEvent *aeSearchNearestTimer(aeEventLoop *eventLoop)
{
aeTimeEvent *te = eventLoop->timeEventHead;
aeTimeEvent *nearest = NULL; while(te)
{
if (!nearest || te->when_sec < nearest->when_sec || (te->when_sec == nearest->when_sec && te->when_ms < nearest->when_ms))
nearest = te;
te = te->next;
}
return nearest;
}
/* Process time events 处理时间事件,先执行定时器事件,如果有时间设置过端的情况,会导致整个卡死*/
static int processTimeEvents(aeEventLoop *eventLoop)
{
int processed = ;
aeTimeEvent *te;
long long maxId;
time_t now = time(NULL); if (now < eventLoop->lastTime) /*为啥会出现当前时间小于上次激活时间的问题,重新设置了系统时间,当前时间小于了最后的插入时间*/
{
te = eventLoop->timeEventHead;
while(te)
{
te->when_sec = ;
te = te->next;
}
}
eventLoop->lastTime = now;/*更新最后操作时间*/ te = eventLoop->timeEventHead;
maxId = eventLoop->timeEventNextId-;
/*时间处理,从链表中逐个检查,找到到达时间的定时器后调用处理函数,然后重新从头遍历,当某个定时器的*/
while(te)
{
long now_sec, now_ms;
long long id; if (te->id > maxId)
{
te = te->next;
continue;
}
aeGetTime(&now_sec, &now_ms);
if (now_sec > te->when_sec || (now_sec == te->when_sec && now_ms >= te->when_ms))
{/*当该节点时间到达时,调用时间处理函数,根据函数的返回来决定是否需要删除定时节点*/
int retval; id = te->id;
retval = te->timeProc(eventLoop, id, te->clientData);
processed++; /*根据函数的返回值来确定是否仍需注册,返回值为下次的激活时间*/
if (retval != AE_NOMORE)
{
/*返回值不为-1时需要重新注册函数,返回值为下次激活的时间*/
aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);
}
else
{
/*删除定时器*/
aeDeleteTimeEvent(eventLoop, id);
}
/*定时器函数处理完毕之后为了防止漏掉节点,重新从头结点遍历,这个地方要注意,如果定时时间太短,这个地方会造成死循环,不停的处理定时器事件*/
te = eventLoop->timeEventHead;
}
else
{
te = te->next;
}
}
return processed;
}
Redis事件管理(二)的更多相关文章
- Redis事件管理(一)
Redis统一的时间管理器,同时管理文件事件和定时器, 这个管理器的定义: #if defined(__APPLE__) #define HAVE_TASKINFO 1 #endif /* Test ...
- Redis事件管理(三)
Redis的事件管理和定时器的管理都是自己来实现的,Redis的事件管理分为两部分,一部分是封装了系统的异步事件API,还有一部分是在这基础上封装了一个通用的事件管理器,根据具体的系统来决定具体使用哪 ...
- zendframework 事件管理(二)
首先需要明确的几个问题: Q1.什么是事件? A:事件就是一个有名字的行为.当这个行为发生的时候,称这个事件被触发. Q2.监听器又是什么? A:监听器决定了事件的逻辑表达,由事件触发.监听器和事件往 ...
- redis的管理工具
phpredisadmin工具 rdbtools管理工具 saltstack管理redis 通过codis完成redis管理 一:phpredisadmin工具:类似于mysqladmin管理mysq ...
- Redis事件
Redis事件 Redis的ae(Redis用的事件模型库) ae.c Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件: 文件事件(file event):Redis服务器通过套接字与 ...
- 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理
服务器文档下载zip格式 刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...
- jquery技巧之让任何组件都支持类似DOM的事件管理
本文介绍一个jquery的小技巧,能让任意组件对象都能支持类似DOM的事件管理,也就是说除了派发事件,添加或删除事件监听器,还能支持事件冒泡,阻止事件默认行为等等.在jquery的帮助下,使用这个方法 ...
- Redis 内存管理与事件处理
1 Redis内存管理 Redis内存管理相关文件为zmalloc.c/zmalloc.h,其只是对C中内存管理函数做了简单的封装,屏蔽了底层平台的差异,并增加了内存使用情况统计的功能. void * ...
- 安装window下的redis,redis可视化管理工具(Redis Desktop Manager)安装,基础使用,实例化项目
以下包括内容: 一.redis下载安装,启动 二.Redis可视化管理工具(Redis Desktop Manager)安装 三.实例化项目 一.redis下载安装,启动 1,redis官方下载地址: ...
随机推荐
- SQL中关于日期的常用方法
mysql数据库: logintime >= STR_TO_DATE('$$START_TIME','%Y-%m-%d %H:%i:%s') AND logintime < STR_TO_ ...
- Swift3.0P1 语法指南——字符串与字符
原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...
- .NET异步编程之回调
C#中异步和多线程的区别是什么呢?异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性.甚至有些时候我们就认为异步和多线程是等同的概念.但是,异步和多线程还是有一些区别的.而这些区 ...
- shell简单使用
最近需要用到shell脚本实现关机保护作用,总结下语法 要点: 1.linux下编写的shell脚本不能在window下编写,否则会出现^M的错误,用window编写保存,在linux用vim打开,每 ...
- js实现自定义右键菜单--兼容IE、Firefox、Chrome
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- hibernate 的三种状态 如何转化的。
1. 临时状态 由 new命令开辟内存空间的java对象,例如: User user=new User(); 临 时对象在内存孤立存在,它是携带信息的载体,不和数据库的数据有任何关联关系. 2. ...
- unity销毁层级物体及 NGUI 深度理解总结
http://www.2cto.com/kf/201311/258811.html 1.想找到层级面板中某个物体,并销毁,利用下面的代码: GameObject obj = GameObjec ...
- python 数据结构 初学时没太注意却发现很有用的点点滴滴
1. list.extend(L) 将指定列表中的所有元素附加到另一个列表的末尾:相当于a[len(a):] = L. 2. list.pop([i]) 删除列表中指定位置的元素并返回它.如果未指定索 ...
- angularjs表达式中的HTML内容,如何不转义,直接表现为html元素
在模板中直接: 在ionic中直接使用: <p class="contentwen" ng-bind-html="detial.content">& ...
- 线段树基础模板&&扫描线
线段树的单点更新+区间求和 hdu1166敌兵布阵 Input 第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N<=),表示敌人有N个工兵营地 ,接下来有N个正整数,第i个正整 ...