【数据结构】C++语言无锁环形队列的实现
无锁环形队列
- 1.Ring_Queue在payload前加入一个头,来表示当前节点的状态
- 2.当前节点的状态包括可以读、可以写、正在读、正在写
- 3.当读完成后将节点状态改为可以写,当写完成后将节点状态改为可以读
- 4.Ring_Queue使用时参照生产者消费者模型,生产者生产(写)一个可用节点,消费者获得(读)队列头节点
Github地址: https://github.com/HITFishily/CandCPP
/**************************************************************************************************
* File Name : ring_queue_nolock.h
* Created : 20 / 02 / 10
* Author : GYT
* Description : 无锁环形队列
* 1.Ring_Queue在payload前加入一个头,来表示当前节点的状态
* 2.当前节点的状态包括可以读、可以写、正在读、正在写
* 3.当读完成后将节点状态改为可以写,当写完成后将节点状态改为可以读
* 4.Ring_Queue使用时参照生产者消费者模型,生产者生产(写)一个可用节点,消费者获得(读)队列头节点
**************************************************************************************************/
#include <assert.h>
#include <string.h>
#include <sys/types.h>
typedef unsigned char u_char;
#define CAN_WRITE 0x00
#define CAN_READ 0x01
#define READING 0x02
#define WRITING 0x03
typedef struct tag
{
u_char tag_value;
}TAG;
class Ring_Queue
{
public:
/**************************************************************************************************
* Function Name : Ring_Queue
* Description : 构造函数
* Date : 20 / 02 / 10
* Parameter : int nmemb:队列大小 int size:Payload长度
* Return Code : none
* Author : GYT
**************************************************************************************************/
Ring_Queue(int nmemb, int size):m_inmemb(nmemb), m_isize(size)
, m_iread_now(0), m_iwrite_now(0)
{
if (nmemb <= 0 || size <= 0)
{
assert(0);
}
m_queue_p = NULL;
m_queue_p = new u_char[nmemb * (sizeof(TAG)+size)];
memset(m_queue_p, 0, nmemb * (sizeof(TAG)+size));
}
/**************************************************************************************************
* Function Name : Ring_Queue
* Description : 析构函数
* Date : 20 / 02 / 10
* Parameter : none
* Return Code : none
* Author : GYT
**************************************************************************************************/
~Ring_Queue()
{
if (m_queue_p) delete[]m_queue_p;
}
/**************************************************************************************************
* Function Name : Read
* Description : 读取函数
* Date : 20 / 02 / 10
* Parameter : none
* Return Code : 指向payload的指针
* Author : GYT
**************************************************************************************************/
u_char * Read();
/**************************************************************************************************
* Function Name : Read_Over
* Description : 读取之后的操作,将节点状态跟更新为‘可以写’,并将可读节点指向下一个位置
* Date : 20 / 02 / 10
* Parameter : none
* Return Code : none
* Author : GYT
**************************************************************************************************/
void Read_Over();
/**************************************************************************************************
* Function Name : Write
* Description : 写入函数
* Date : 20 / 02 / 10
* Parameter : none
* Return Code : 此时返回一个安全的、可以用来写数据的指针,具体的写入操作由生产者执行
* Author : GYT
**************************************************************************************************/
u_char * Write();
/**************************************************************************************************
* Function Name : Write_Over
* Description : 写入之后的操作,将节点状态跟更新为‘可以读’,并将可写节点指向下一个位置
* Date : 20 / 02 / 10
* Parameter : none
* Return Code : none
* Author : GYT
**************************************************************************************************/
void Write_Over();
private:
/**************************************************************************************************
* Function Name : queue_peek_nth
* Description : 因为整个队列是u_char数组,需要根据字节数偏移至指定位置
* Date : 20 / 02 / 10
* Parameter : u_char *queue_p:队列 int pos:需要偏移的位置
* Return Code : none
* Author : GYT
**************************************************************************************************/
u_char *queue_peek_nth(u_char *queue_p, int pos);
u_char* m_queue_p; //队列指针
int m_inmemb; //队列大小
int m_isize; //队列中存放数据的长度
volatile int m_iread_now; //当前可读节点
volatile int m_iwrite_now; //当前可写节点
};
#include "ring_queue_nolock.h"
u_char * Ring_Queue::Read()
{
u_char * g_p = 0;
TAG * tag_p = 0;
u_char *user_data = 0;
g_p = queue_peek_nth(m_queue_p, m_iread_now);
tag_p = (TAG *)g_p;
if (tag_p->tag_value == CAN_READ)
{
user_data = (u_char *)g_p + sizeof(TAG);
tag_p->tag_value = READING;
}
return user_data;
}
void Ring_Queue::Read_Over()
{
u_char * g_p = 0;
TAG * tag_p = 0;
g_p = queue_peek_nth(m_queue_p, m_iread_now);
tag_p = (TAG *)g_p;
if (tag_p->tag_value == READING)
{
tag_p->tag_value = CAN_WRITE;
m_iread_now = (m_iread_now + 1) % m_inmemb;
}
}
u_char * Ring_Queue::Write()
{
u_char * g_p = 0;
TAG * tag_p = 0;
u_char *user_data = 0;
g_p = queue_peek_nth(m_queue_p, m_iwrite_now);
tag_p = (TAG *)g_p;
if (tag_p->tag_value == CAN_WRITE)
{
user_data = (u_char *)g_p + sizeof(TAG);
tag_p->tag_value = WRITING;
}
return user_data;
}
void Ring_Queue::Write_Over()
{
u_char * g_p = 0;
TAG * tag_p = 0;
g_p = queue_peek_nth(m_queue_p, m_iwrite_now);
tag_p = (TAG *)g_p;
if (tag_p->tag_value == WRITING)
{
tag_p->tag_value = CAN_READ;
m_iwrite_now = (m_iwrite_now + 1) % m_inmemb;
}
}
u_char* Ring_Queue::queue_peek_nth(u_char *queue_p, int pos)
{
u_char *rst = 0;
if (queue_p && pos < m_inmemb)
{
rst = queue_p + pos * (sizeof(TAG)+m_isize);
}
return rst;
}
【数据结构】C++语言无锁环形队列的实现的更多相关文章
- DPDK 无锁环形队列(Ring)详解
DPDK 无锁环形队列(Ring) 此篇文章主要用来学习和记录DPDK中无锁环形队列相关内容,结合了官方文档说明和源码中的实现,供大家交流和学习. Author : Toney Email : vip ...
- Linux 内核:匠心独运之无锁环形队列kfifo
Linux 内核:匠心独运之无锁环形队列 Kernel version Linux 2.6.12 Author Toney Email vip_13031075266@163.com Da ...
- 理解 Memory barrier(内存屏障)无锁环形队列
原文:https://www.cnblogs.com/my_life/articles/5220172.html Memory barrier 简介 程序在运行时内存实际的访问顺序和程序代码编写的访问 ...
- 一个无锁消息队列引发的血案(五)——RingQueue(中) 休眠的艺术
目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...
- 一个无锁消息队列引发的血案(四)——月:RingQueue(上) 自旋锁
目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...
- 一个无锁消息队列引发的血案(三)——地:q3.h 与 RingBuffer
目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...
- 一个无锁消息队列引发的血案(六)——RingQueue(中) 休眠的艺术 [续]
目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...
- Go语言无锁队列组件的实现 (chan/interface/select)
1. 背景 go代码中要实现异步很简单,go funcName(). 但是进程需要控制协程数量在合理范围内,对应大批量任务可以使用"协程池 + 无锁队列"实现. 2. golang ...
- linux内核无锁缓冲队列kfifo原理
Linux kernel里面从来就不缺少简洁,优雅和高效的代码 比如,通过限定写入的数据不能溢出和内存屏障实现在单线程写单线程读的情况下不使用锁.因为锁是使用在共享资源可能存在冲突的情况下.还用设置b ...
随机推荐
- Oracle10g下载地址
Oracle Database 10g Release 2 (10.2.0.1.0) Enterprise/Standard Edition for Microsoft Windows (32-bit ...
- 三 MyBatis配置文件SqlMapCofing.xml(属性加载&类型别名配置&映射文件加载)
SqlMapCofing:dtd,属性加载有固定的顺序Content Model properties:加载属性文件 typeAliases:别名配置 1 定义单个别名:不区分大小写 核心配置: 映射 ...
- 第1节 storm日志告警:1、 - 5、日志监控告警业务需求、代码、集群运行、总结
如何解决短信或者邮件频繁发送的问题:每次发送的时候都先查询数据库记录,看一下有没有给这个人发送消息,上一次发送消息的时间是什么时候,如果发送时间间隔小于半个小时,就不要再发了 ============ ...
- Android 用ViewFlipper实现跑马灯效果的公告提示
1.代码部分private void initViewFlipper(final HomepageListModel.Notice notice) { for (int i = 0; i < n ...
- 2019护网杯baby_forensic
题目名称:baby_forensic题目描述:can you catch the flag?附件:“data.7z” 2019护网杯初赛的一道取证题,比赛时没做出来,赛后又研究了一下. 获取profi ...
- python学习笔记(三)---高级特性
一.切片 取无数多个list元素 不用一个个取得笨方法就用切片 对这种经常取指定索引范围的操作,用循环十分繁琐,因此,Python提供了切片(Slice)操作符,能大大简化这种操作. 对应上面的问题, ...
- Python爬虫连载5-Proxy、Cookie解析
一.ProxyHandler处理(代理服务器) 1.使用代理IP,是爬虫的常用手段 2.获取代理服务器的地址: www.xicidaili.com www.goubanjia.com 3.代理用来隐藏 ...
- 简单模拟IOC容器:返回对象并能抛出异常
本次要求:已知com.zzj.vo包下分别有Tiger.lion.Elephant三个Java源文件,请据此实现以下功能:①.自定义一个名为Component的注解,要求该注解只能用于类且代码运行时该 ...
- dubbo-admin的安装使用
dubbo-admin下载地址:https://github.com/apache/incubator-dubbo/releases 可以直接下载到linux上 wget https://github ...
- oracle练习-day04
.什么是PL.PL.普通变量和常量使用) :) :.引用型变量 .记录型变量.条件分支语法:if 条件 .根据输入的年龄判断小于输出未成年人,成年人,以上老年人): .loop循环语法:.输出到的数 ...