nginx队列模块的分析和使用
2013-12-16 15:14
666 查看
nginx队列模块的设计挺精妙的,也算是用一个C语言实现泛型的典型例子了,我将其独立出来,写上注释和测试例子,方便以后查看。
#ifndef _NGX_QUEUE_H_INCLUDED_ #define _NGX_QUEUE_H_INCLUDED_ #include <stdio.h> #include <stddef.h> typedef struct ngx_queue_s ngx_queue_t; //队列的节点,也直接表示队列, //但它不直接保存数据,只保存了前后两个结点的指针 //由下面操作函数可以看出,它是一个带头结点的双向循环队列 struct ngx_queue_s { ngx_queue_t *prev; ngx_queue_t *next; }; //初始化队列q所指向的指针,两个指针都指向它自己, //在这里,q是队列的头结点,起表头的作用,不储存信息 #define ngx_queue_init(q) \ (q)->prev = q; \ (q)->next = q //如果表头的下个结点是它自己,那么这就是一个空队列 #define ngx_queue_empty(h) \ (h == (h)->prev) //向h结点的后面插入一个结点x #define ngx_queue_insert_head(h, x) \ (x)->next = (h)->next; \ (x)->next->prev = x; \ (x)->prev = h; \ (h)->next = x #define ngx_queue_insert_after ngx_queue_insert_head //向h结点的前面插入一个结点x #define ngx_queue_insert_tail(h, x) \ (x)->prev = (h)->prev; \ (x)->prev->next = x; \ (x)->next = h; \ (h)->prev = x //表头的第下一个结点就是第一个储存数据的结点 #define ngx_queue_head(h) \ (h)->next //表头的第上一个结点就是最后一个储存数据的结点 #define ngx_queue_last(h) \ (h)->prev #define ngx_queue_sentinel(h) \ (h) //获取下一个结点 #define ngx_queue_next(q) \ (q)->next //获取上一个结点 #define ngx_queue_prev(q) \ (q)->prev #if (NGX_DEBUG) #define ngx_queue_remove(x) \ (x)->next->prev = (x)->prev; \ (x)->prev->next = (x)->next; \ (x)->prev = NULL; \ (x)->next = NULL #else //删除X结点,调整其指针 #define ngx_queue_remove(x) \ (x)->next->prev = (x)->prev; \ (x)->prev->next = (x)->next #endif //分割队列 #define ngx_queue_split(h, q, n) \ (n)->prev = (h)->prev; \ (n)->prev->next = n; \ (n)->next = q; \ (h)->prev = (q)->prev; \ (h)->prev->next = h; \ (q)->prev = n; //将以n为表头的队列接到以h为表头的队列后面 #define ngx_queue_add(h, n) \ (h)->prev->next = (n)->next; \ (n)->next->prev = (h)->prev; \ (h)->prev = (n)->prev; \ (h)->prev->next = h; //寻找包含line(ngx_queue_t)成员的结构体,返回这个结构体的指针 #define ngx_queue_data(q, type, link) \ (type *) ((char *) q - offsetof(type, link)) ngx_queue_t *ngx_queue_middle(ngx_queue_t *queue); void ngx_queue_sort(ngx_queue_t *queue, int (*cmp)(const ngx_queue_t *, const ngx_queue_t *)); #endif /* _NGX_QUEUE_H_INCLUDED_ */ //寻找队列的中点 //从表头开始,middle指针每次前进一个结点,next指针每次前进两个结点 //那么,next指针到达表尾时,middle ngx_queue_t * ngx_queue_middle(ngx_queue_t *queue) { ngx_queue_t *middle, *next; middle = ngx_queue_head(queue); if (middle == ngx_queue_last(queue)) { return middle; } next = ngx_queue_head(queue); for ( ;; ) { middle = ngx_queue_next(middle); next = ngx_queue_next(next); if (next == ngx_queue_last(queue)) { return middle; } next = ngx_queue_next(next); if (next == ngx_queue_last(queue)) { return middle; } } } //用稳定插入法排序该队列 void ngx_queue_sort(ngx_queue_t *queue, int (*cmp)(const ngx_queue_t *, const ngx_queue_t *)) { ngx_queue_t *q, *prev, *next; q = ngx_queue_head(queue); if (q == ngx_queue_last(queue)) { return; } for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) { prev = ngx_queue_prev(q); next = ngx_queue_next(q); ngx_queue_remove(q); do { if (cmp(prev, q) <= 0) { break; } prev = ngx_queue_prev(prev); } while (prev != ngx_queue_sentinel(queue)); ngx_queue_insert_after(prev, q); } } ////////////////////////////////////////////////////////////////////////// //使用例子 //若想使用ngx_queue_t的功能,只需在自己的结构体中包含一个ngx_queue_t成员就可以了 //(当然,初始化的时候要小心) typedef struct { int num; char str[1024]; ngx_queue_t queue; }TestNode; //TestNode比较函数 int CompTestNode(const ngx_queue_t *a, const ngx_queue_t *b) { TestNode *anode = ngx_queue_data(a, TestNode, queue); TestNode *bnode = ngx_queue_data(b, TestNode, queue); return anode->num > bnode->num; } //输出整个TestNode队列 void PrintNodeQueue(const ngx_queue_t *que) { ngx_queue_t *q; //遍历整个队列 for( q = ngx_queue_head(que); q != ngx_queue_sentinel(que); q = ngx_queue_next(q) ) { TestNode *node = ngx_queue_data(q, TestNode, queue); printf("%d %s\n", node->num, node->str); } } int main() { TestNode node[10]; int i; ngx_queue_t content; ngx_queue_init(&content); for(i=0; i<10; i++) { node[i].num = i; sprintf(node[i].str, "%d--%d--%d", i, i, i); ngx_queue_insert_head(&content, &node[i].queue); } PrintNodeQueue(&content); ngx_queue_sort(&content, CompTestNode); printf("\nAfter sort:\n"); PrintNodeQueue(&content); return 0; }
相关文章推荐
- Nginx源码分析-定时器的实现及使用
- 使用nginx的ngx_upstream_jdomain模块实现k8s容器的负载均衡
- nginx使用ssl模块配置HTTPS支持
- nginx访问限制模块limit_conn_zone 和limit_req_zone配置使用详解
- nginx使用ssl模块配置HTTPS支持
- Python之队列queue模块使用 常见问题与用法
- 使用python分析nginx访问日志
- 使用Nginx中自带的模块配置缩略图功能的教程
- nginx 限速模块的使用
- 使用awstats分析nginx
- PHP扩展模块memcached长连接使用方法分析
- 使用 awstats 分析 Nginx 的访问日志
- nginx+php的配置(使用nginx的fastcgi模块)
- Nginx源码分析---队列结构ngx_queue_t
- 使用memc-nginx和srcache-nginx模块构建高效透明的缓存机制
- 使用Intel VTune性能分析器分析.NET模块运行时间
- python pandas做数据分析视图分析matplotlib,seaborn模块使用
- 文章5:Linux下使用Eclipse进行Nginx 模块开发
- nginx使用ssl模块配置支持HTTPS访问【解决ssl错误】
- nginx日志分析手机使用频次