Libev源码分析01:Libev中的监视器结构(C结构体实现继承)
在Libev的源码中,用到了一种用C实现类似C++中继承的技巧,主要是用宏和结构体实现。
在Libev中,最关键的数据结构就是各种监视器,比如IO监视器,信号监视器等等。这些监视器的多数成员都是一样的,只有少部分成员为各自独有。这就非常类似于C++中继承的使用场景了。废话少说,代码如下(略有改动,某些宏做了展开):
# define EV_CB_DECLARE(type) void (*cb)(struct ev_loop *loop, struct type *w, int revents); #define EV_WATCHER(type) \
int active; /* private */ \
int pending; /* private */ \
int priority; /* private */ \
void *data; /* rw */ \
EV_CB_DECLARE (type) /* private */ #define EV_WATCHER_LIST(type) \
EV_WATCHER (type) \
struct ev_watcher_list *next; /* private */ typedef struct ev_watcher
{
EV_WATCHER (ev_watcher)
} ev_watcher; typedef struct ev_watcher_list
{
EV_WATCHER_LIST (ev_watcher_list)
} ev_watcher_list; typedef struct ev_io
{
EV_WATCHER_LIST (ev_io)
int fd; /* ro */
int events; /* ro */
} ev_io; typedef struct ev_signal
{
EV_WATCHER_LIST (ev_signal)
int signum; /* ro */
} ev_signal;
ev_watcher是所有结构的“基类”,宏EV_WATCHER定义了它的所有成员。像IO监视器、信号监视器等是以链表的形式进行组织的,所以,在ev_watcher基类的基础上,定义了ev_watcher的子类ev_watcher_list,宏EV_WATCHER_LIST就定义了该基类的所有成员。
ev_io和ev_signal相当于ev_watcher_list的子类,它们的前5个成员于ev_watcher相同,前6个成员与ev_watcher_list相同。
上面的代码可能还不是太清楚,下面将上面代码中的所有宏都展开,代码如下:
# define EV_CB_DECLARE(type) void (*cb)(struct ev_loop *loop, struct type *w, int revents); #define EV_WATCHER(type) \
int active; /* private */ \
int pending; /* private */ \
int priority; /* private */ \
void *data; /* rw */ \
EV_CB_DECLARE (type) /* private */ #define EV_WATCHER_LIST(type) \
int active; /* private */ \
int pending; /* private */ \
int priority; /* private */ \
void *data; /* rw */ \
EV_CB_DECLARE (type) /* private */ \
struct ev_watcher_list *next; /* private */ typedef struct ev_watcher
{
int active;
int pending;
int priority;
void *data;
EV_CB_DECLARE (ev_watcher)
} ev_watcher; typedef struct ev_watcher_list
{
int active;
int pending;
int priority;
void *data;
EV_CB_DECLARE (ev_watcher_list)
struct ev_watcher_list *next;
} ev_watcher_list; typedef struct ev_io
{
int active;
int pending;
int priority;
void *data;
EV_CB_DECLARE (ev_io)
struct ev_watcher_list *next; int fd; /* ro */
int events; /* ro */
} ev_io; typedef struct ev_signal
{
int active;
int pending;
int priority;
void *data;
EV_CB_DECLARE (ev_signal)
struct ev_watcher_list *next;
int signum;
} ev_signal;
下面是Libev中如何使用这些结构体的代码:
void ev_start (struct ev_loop *loop, ev_watcher* w, int active)
{
...
w->active = active;
...
} void wlist_add (ev_watcher_list **head, ev_watcher_list *elem)
{
elem->next = *head;
*head = elem;
} void ev_io_start (struct ev_loop *loop, ev_io *w)
{
...
ev_start (loop, (ev_watcher*)w, 1);
...
wlist_add (&anfds[fd].head, (ev_watcher_list *)w);
}
在ev_io_start函数中,w是指向ev_io结构的指针,使用ev_start函数设置其成员active时,将其强制转换成基类ev_watcher,在将其添加进链表时,又将其强制转化为ev_watcher_list类型。
下面的代码是模拟上面的方法,写出的例子代码:
typedef struct
{
char *color;
int weight;
}fruit; typedef struct fruitlist
{
char *color;
int weight;
struct fruitlist *next;
}fruitlist; typedef struct
{
char *color;
int weight;
struct fruitlist *next;
char *taste;
}apple; void setcolorweight(fruit *f, char *color, int weight)
{
f->color = color;
f->weight = weight;
} void putinlist(fruitlist **head, fruitlist *ele)
{
ele->next = *head;
*head = ele;
}
void testinherit()
{
fruitlist *head = NULL; apple ap1;
setcolorweight((fruit *)&ap1, "red", 2);
ap1.taste = "sweet";
putinlist(&head, (fruitlist *)&ap1); apple ap2;
setcolorweight((fruit *)&ap2, "yellow", 1);
ap2.taste = "sour";
putinlist(&head, (fruitlist *)&ap2); fruitlist *p = head;
while(p != NULL)
{
printf("color is %s, weight is %d\n", p->color, p->weight);
p = (fruitlist *)(p->next);
}
}
结果如下:
color is yellow, weight is 1
color is red, weight is 2
Libev源码分析01:Libev中的监视器结构(C结构体实现继承)的更多相关文章
- [转]Libev源码分析 -- 整体设计
Libev源码分析 -- 整体设计 libev是Marc Lehmann用C写的高性能事件循环库.通过libev,可以灵活地把各种事件组织管理起来,如:时钟.io.信号等.libev在业界内也是广受好 ...
- 一个由正则表达式引发的血案 vs2017使用rdlc实现批量打印 vs2017使用rdlc [asp.net core 源码分析] 01 - Session SignalR sql for xml path用法 MemCahe C# 操作Excel图形——绘制、读取、隐藏、删除图形 IOC,DIP,DI,IoC容器
1. 血案由来 近期我在为Lazada卖家中心做一个自助注册的项目,其中的shop name校验规则较为复杂,要求:1. 英文字母大小写2. 数字3. 越南文4. 一些特殊字符,如“&”,“- ...
- angular源码分析:angular中脏活累活的承担者之$interpolate
一.首先抛出两个问题 问题一:在angular中我们绑定数据最基本的方式是用两个大括号将$scope的变量包裹起来,那么如果想将大括号换成其他什么符号,比如换成[{与}],可不可以呢,如果可以在哪里配 ...
- angular源码分析:angular中入境检察官$sce
一.ng-bing-html指令问题 需求:我需要将一个变量$scope.x = '<a href="http://www.cnblogs.com/web2-developer/&qu ...
- angular源码分析:angular中各种常用函数,比较省代码的各种小技巧
angular的工具函数 在angular的API文档中,在最前面就是讲的就是angular的工具函数,下面列出来 angular.bind //用户将函数和对象绑定在一起,返回一个新的函数 angu ...
- angular源码分析:angular中的依赖注入式如何实现的
一.准备 angular的源码一份,我这里使用的是v1.4.7.源码的获取,请参考我另一篇博文:angular源码分析:angular源代码的获取与编译环境安装 二.什么是依赖注入 据我所知,依赖注入 ...
- NIO 源码分析(01) NIO 最简用法
目录 一.服务端 二.客户端 NIO 源码分析(01) NIO 最简用法 Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) J ...
- openVswitch(OVS)源码分析之工作流程(哈希桶结构体的解释)
这篇blog是专门解决前篇openVswitch(OVS)源码分析之工作流程(哈希桶结构体的疑惑)中提到的哈希桶结构flex_array结构体成员变量含义的问题. 引用下前篇blog中分析讨论得到的f ...
- Libev源码分析09:select突破处理描述符个数的限制
众所周知,Linux下的多路复用函数select采用描述符集表示处理的描述符.描述符集的大小就是它所能处理的最大描述符限制.通常情况下该值为1024,等同于每个进程所能打开的描述符个数. 增大描述符集 ...
随机推荐
- Struts_改写客户列表练习
1.CustomerAction修改放入ActionContext 2.list.jsp使用struts标签库
- 【CS Round #44 (Div. 2 only) C】Check DFS
[链接]点击打开链接 [题意] 给你一个n节点,m条边的无向联通图. 给你一个节点访问的顺序.(1..n的排列) 你可以改变每个点优先访问的出度.(但必须按照dfs的规则); 问你能不能按照所给的访问 ...
- leetcode 60-80 easy
66.Plus One Given a non-empty array of digits representing a non-negative integer, plus one to the i ...
- React高阶组件 和 Render Props
高阶组件 本质 本质是函数,将组件作为接收参数,返回一个新的组件.HOC本身不是React API,是一种基于React组合的特而形成的设计模式. 解决的问题(作用) 一句话概括:功能的复用,减少代码 ...
- Vue. 之 Element获取table中选中的行
Vue. 之 Element获取table中选中的行 问题描述: 如下截图,在Table中选择数据后,然后在点击“统计”按钮,获取Table表中选择的行 解决方案: 1. 给“统计”这个按钮添加一个点 ...
- [Vue CLI 3] vue inspect 的源码设计实现
首先,请记住: 它在新版本的脚手架项目里面非常重要 它有什么用呢? inspect internal webpack config 能快速地在控制台看到对应生成的 webpack 配置对象. 首先它是 ...
- Pyhton AES_cbc解密
最近很多朋友问我加密解密有没有啥好推荐的方式,一般对AES的加密解密方式直接用在线加密或者解密就行,我为了方便测试,将网址以python脚本的形式写了出来,很简单的东西,2分钟搞定,随手记录一下~~ ...
- tomcat的日志不输出日志信息的解决方法
1.下载日志jar包,例如:commons-logging-1.1.1.jar.放在tomcat的bin目录下,或者是自己项目的lib包里. 2.修改tomcat的bin目录下面的catalina.b ...
- 【水滴石穿】ReactNativeDemo
这个博主他的功底算是特别棒的了,能够把一些基础的例子,通过精巧的方式布局在一个小的demo里面 很值得我学习 放上博主的链接:https://github.com/jianiuqi/ReactNati ...
- 一个基于Asterisk构建的VOIP应用软件:Elastix介绍
Elastix 是一种应用软件,它整合了适用于那些基于 Asterisk 的 PBX 的最好工具,并将它们集成为单一的.易用的接口.同时,它增加了自己的工具集,以及允许创建第三方模块来使 Elasti ...