zeromq源码学习——yqueue
来源:互联网 发布:淘宝买家售后申请退款 编辑:程序博客网 时间:2024/06/08 02:44
yqueue是一个高效的队列实现,能够减少内存分配和释放的次数。yqueue可以在一个线程中调用push/back函数,在另一个线程中调用pop/front函数。但是要确保不会pop一个空队列,并且两个线程不能在无锁条件下访问同一个元素。
yqueue中为一个chunk_t类型的双向链表,每个chunk里保存有N个元素。pos表示当前chunk中所指向的有效元素位置,通过增加pos可以实现快速的push/pop操作。back_chunk和end_chunk的区别为:back_chunk指向最后一个有效的元素,end_chunk指向下一个push位置。
yqueue的操作没有做有效性检查,一切操作需要调用者确保安全性。
yqueue源码:
//T是队列中对象类型//N是队列粒度,用来减少内存分配和释放次数template <typename T, int N> class yqueue_t{public: //构造函数 inline yqueue_t () { begin_chunk = allocate_chunk(); alloc_assert (begin_chunk); begin_pos = 0; back_chunk = NULL; back_pos = 0; end_chunk = begin_chunk; end_pos = 0; } //析构函数 inline ~yqueue_t () { while (true) { if (begin_chunk == end_chunk) { free (begin_chunk); break; } chunk_t *o = begin_chunk; begin_chunk = begin_chunk->next; free (o); } chunk_t *sc = spare_chunk.xchg (NULL); free (sc); } //返回队列第一个元素,队列为空,则行为未定义 inline T &front () { return begin_chunk->values [begin_pos]; } //返回队列最后一个元素,队列为空,则行为未定义 inline T &back () { return back_chunk->values [back_pos]; } //从队尾压入元素 inline void push () { back_chunk = end_chunk; back_pos = end_pos; if (++end_pos != N) return; chunk_t *sc = spare_chunk.xchg (NULL); if (sc) { end_chunk->next = sc; sc->prev = end_chunk; } else { end_chunk->next = allocate_chunk(); alloc_assert (end_chunk->next); end_chunk->next->prev = end_chunk; } end_chunk = end_chunk->next; end_pos = 0; } //回滚上次压入操作。 //注:调用者需要负责销毁unpush对象。调用者要确保unpush时队列非空。该调用是非线程安全的。 inline void unpush () { //首先,移除最后一个位置的元素 if (back_pos) --back_pos; else { back_pos = N - 1; back_chunk = back_chunk->prev; } if (end_pos) --end_pos; else { end_pos = N - 1; end_chunk = end_chunk->prev; free (end_chunk->next); end_chunk->next = NULL; } } //队尾移除元素 inline void pop () { //++begin_pos==N,表示第一个内存块用尽 if (++ begin_pos == N) { chunk_t *o = begin_chunk; begin_chunk = begin_chunk->next; begin_chunk->prev = NULL; begin_pos = 0; //保存最近一次释放的内存块 chunk_t *cs = spare_chunk.xchg (o); free (cs); } }private: //持有N个元素的内存块,实现为一个双向队列 struct chunk_t { T values [N]; chunk_t *prev; chunk_t *next; }; //内存块分配函数 inline chunck_t *allocate_chunk() { //省略内存定义内存对齐时的调用 return (chunck_t*) malloc(sizeof(chunck_t)); } chunk_t *begin_chunk;//第一个内存块 int begin_pos; chunk_t *back_chunk;//指向最后一个有效元素块 int back_pos; chunk_t *end_chunk;//指向下一个可压入元素块 int end_pos; //大多数情况下,生产和消费频率相近,因此保存最近一次释放的内存块(从queue中去除,但内存未释放),减少内存释放和分配频率 atomic_ptr_t<chunk_t> spare_chunk; //禁止拷贝 yqueue_t (const yqueue_t&); const yqueue_t &operator = (const yqueue_t&);};
阅读全文
0 0
- zeromq源码学习——yqueue
- zeromq源码学习——ypipe
- zeromq源码学习——array
- zeromq源码学习——ctx创建
- zeromq分析-1-yqueue实现
- zeromq应用学习(1)——编译zeromq的示例程序
- zeromq源代码分析5-1------管道相关的数据结构yqueue, ypipe, pipe等
- zeromq源代码分析5-2------管道相关的数据结构yqueue, ypipe, pipe等
- zeromq源代码分析5-3------管道相关的数据结构yqueue, ypipe, pipe等
- zeromq 学习
- zeroMQ学习
- zeromq学习
- zeromq 学习
- ZeroMQ 学习
- ZeroMQ学习
- zeromq源码阅读 —— Msg.hpp & Msg.cpp 的 msg_t (zmq中的消息)
- ZeroMQ 源码阅读
- ZeroMQ,史上最快的消息队列 —– ZMQ的学习和研究
- 排序 归并排序+快排
- ADO参考手册
- Apple Watch 编程指南(中文版)
- 安卓webview长按分享,长按选择,长按复制,仿好奇心日报长按分享自定义弹窗的实现
- fragment中getactivity为空
- zeromq源码学习——yqueue
- vue.js中字符串倒转
- 当前时间到凌晨的毫秒数
- resource角色隐式授权unlimited tablespace权限测试
- 正则表达式(总结)
- obc学习笔记3
- gcc和g++
- 电影购票APP实现(2)-Servlet
- 提升linux下tcp服务器并发连接数限制