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官方下载地址: ...
随机推荐
- eclipse如何导入java项目文件
平时下载到项目时,希望能够导入到eclipse中使用.但有些项目不能直接导入,需要做转换. 打开源文件目录,查询如下: 如果目录中包含pom.xml文件,则说明该项目由Maven构建的,参考以下 如何 ...
- SpringBoot使用的心得记录
security配置 import com.yineng.corpsysland.security.*; import com.yineng.corpsysland.web.filter.Author ...
- Win7 x64bit安装Oracle10g
解决方案: 步骤一:在解压出的oracle文件夹中搜索refhost.xml文件,搜索结果出现2条符合条件文件,这两个文件均需要修改. 打开文件发现内容中有包含...5.0 6.0等系统说明, ...
- Xcode 7 App Transport Security has blocked a cleartext HTTP 报错解决办法
Xcode 7 创建新项目用到 UIWebView 发送请求时,报下面的错: “App Transport Security has blocked a cleartext HTTP (http:// ...
- WebStorm设置左侧菜单栏背景色和样式
WebStrom一直以来都是默认的白色主题,今天想修改了下主题皮肤,结果导致左侧项目资源栏和顶部菜单栏也变成了黑色,结果无法改变回来,网上查了各种帖子,居然也没找到解决方法,自己研究了半天,终于搞定了 ...
- 2.1---删除链表中重复元素(CC150)
分成两种,1种开了额外空间,临时缓冲区,一种没有开 import java.util.HashSet; import java.util.Set; class ListNode{ int data; ...
- mysql 数据库字符集的指定
create database mydb default character set utf8 default collate utf8_general_ci;
- [转]Python的ASCII, GB2312, Unicode , UTF-8
2007-12-13 10:50:47| 分类: Python实用软件编|举报|字号 订阅 ASCII 是一种字符集,包括大小写的英文字母.数字.控制字符等,它用一个字节表示,范围是 0-1 ...
- C#调用有有参有返的存储过程
(1)在SQL Server中建立如下的存储过程: set ANSI_NULLS ONset QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [dbo].[GetName ...
- discuz内置常用CSS代码分析
CSS多IE下兼容HACK写法 所有 IE浏览器适用:.ie_all .foo { ... } IE6 专用:.ie6 .foo { ... } IE7 专用:.ie7 .foo { ... } IE ...