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事件管理(二)的更多相关文章

  1. Redis事件管理(一)

    Redis统一的时间管理器,同时管理文件事件和定时器, 这个管理器的定义: #if defined(__APPLE__) #define HAVE_TASKINFO 1 #endif /* Test ...

  2. Redis事件管理(三)

    Redis的事件管理和定时器的管理都是自己来实现的,Redis的事件管理分为两部分,一部分是封装了系统的异步事件API,还有一部分是在这基础上封装了一个通用的事件管理器,根据具体的系统来决定具体使用哪 ...

  3. zendframework 事件管理(二)

    首先需要明确的几个问题: Q1.什么是事件? A:事件就是一个有名字的行为.当这个行为发生的时候,称这个事件被触发. Q2.监听器又是什么? A:监听器决定了事件的逻辑表达,由事件触发.监听器和事件往 ...

  4. redis的管理工具

    phpredisadmin工具 rdbtools管理工具 saltstack管理redis 通过codis完成redis管理 一:phpredisadmin工具:类似于mysqladmin管理mysq ...

  5. Redis事件

    Redis事件 Redis的ae(Redis用的事件模型库) ae.c Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件: 文件事件(file event):Redis服务器通过套接字与 ...

  6. 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理

    服务器文档下载zip格式   刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...

  7. jquery技巧之让任何组件都支持类似DOM的事件管理

    本文介绍一个jquery的小技巧,能让任意组件对象都能支持类似DOM的事件管理,也就是说除了派发事件,添加或删除事件监听器,还能支持事件冒泡,阻止事件默认行为等等.在jquery的帮助下,使用这个方法 ...

  8. Redis 内存管理与事件处理

    1 Redis内存管理 Redis内存管理相关文件为zmalloc.c/zmalloc.h,其只是对C中内存管理函数做了简单的封装,屏蔽了底层平台的差异,并增加了内存使用情况统计的功能. void * ...

  9. 安装window下的redis,redis可视化管理工具(Redis Desktop Manager)安装,基础使用,实例化项目

    以下包括内容: 一.redis下载安装,启动 二.Redis可视化管理工具(Redis Desktop Manager)安装 三.实例化项目 一.redis下载安装,启动 1,redis官方下载地址: ...

随机推荐

  1. eclipse如何导入java项目文件

    平时下载到项目时,希望能够导入到eclipse中使用.但有些项目不能直接导入,需要做转换. 打开源文件目录,查询如下: 如果目录中包含pom.xml文件,则说明该项目由Maven构建的,参考以下 如何 ...

  2. SpringBoot使用的心得记录

    security配置 import com.yineng.corpsysland.security.*; import com.yineng.corpsysland.web.filter.Author ...

  3. Win7 x64bit安装Oracle10g

    解决方案:   步骤一:在解压出的oracle文件夹中搜索refhost.xml文件,搜索结果出现2条符合条件文件,这两个文件均需要修改.   打开文件发现内容中有包含...5.0 6.0等系统说明, ...

  4. Xcode 7 App Transport Security has blocked a cleartext HTTP 报错解决办法

    Xcode 7 创建新项目用到 UIWebView 发送请求时,报下面的错: “App Transport Security has blocked a cleartext HTTP (http:// ...

  5. WebStorm设置左侧菜单栏背景色和样式

    WebStrom一直以来都是默认的白色主题,今天想修改了下主题皮肤,结果导致左侧项目资源栏和顶部菜单栏也变成了黑色,结果无法改变回来,网上查了各种帖子,居然也没找到解决方法,自己研究了半天,终于搞定了 ...

  6. 2.1---删除链表中重复元素(CC150)

    分成两种,1种开了额外空间,临时缓冲区,一种没有开 import java.util.HashSet; import java.util.Set; class ListNode{ int data; ...

  7. mysql 数据库字符集的指定

    create database mydb default character set utf8 default collate utf8_general_ci;

  8. [转]Python的ASCII, GB2312, Unicode , UTF-8

    2007-12-13 10:50:47|  分类: Python实用软件编|举报|字号 订阅     ASCII 是一种字符集,包括大小写的英文字母.数字.控制字符等,它用一个字节表示,范围是 0-1 ...

  9. C#调用有有参有返的存储过程

    (1)在SQL Server中建立如下的存储过程: set ANSI_NULLS ONset QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [dbo].[GetName ...

  10. discuz内置常用CSS代码分析

    CSS多IE下兼容HACK写法 所有 IE浏览器适用:.ie_all .foo { ... } IE6 专用:.ie6 .foo { ... } IE7 专用:.ie7 .foo { ... } IE ...