linux c++循环缓冲区模板类
一:概述
实际学习和工作中,我们经常会遇到读写大量数据的情况,这个时候我们可能就用到了循环缓冲区。
循环缓冲区在处理大量数据的时候有很大的优点,循环缓冲区在一些竞争问题上提供了一种免锁的机制,免锁的前提是,生产者和消费都只有一个的情况下,否则也要加锁。
二:循环缓冲区的实现理论如下图

三:实现代码如下所示:
//CRecycleQueue.h #include<iostream> //循环缓冲区类模板
template<class T>
class CRecycleQueue{ private:
//循环缓冲区地址指针
T **_queue;
//循环缓冲区读游标 (读的位置)
int _read;
//循环缓冲区写游标 (写的位置)
int _write;
//循环缓冲区的大小
int _size;
//我们姑且称这个变量为掩码,接下来用来作位&运算,从而实现循环缓冲
int _mask; public:
CRecycleQueue(){
_queue = NULL;
_read = ;
_write = ;
_size = ;
_mask = ;
}
//初始化循环缓冲区
bool InitRecycleQueue(int exp){ if( > exp){ return false;
} _read = ;
_write = ;
//传进来一个整数,对1进行位移操作
//比如exp = 4
//_size的二进制表示:1000
_size = << exp;
//_mask的二进制表示:0111
_mask = _size - ;
//分配缓冲区空间
_queue = (T **)new char[sizeof (T *) * _size]; if(NULL == _queue){ return false;
} return true;
}
/*
* size = 1000 mask = 0111
* write或read同mask 作&运算,可以实现循环缓冲区的功能
* 也许你会问这里为什么不使用 % 运算实现循环的循环功能呢?
* 答案是系统 & 运算效率要比 % 运算效率高
*
* Push:
* write = 0;
* 0000 & 0111 = 0; write++ (写入缓冲队列的第0位置)
* write = 1;
* 0001 & 0111 = 1; write++ (写入缓冲队列的第1位置)
* write = 2;
* 0010 & 0111 = 2; write++
* write = 3;
* 0011 & 0111 = 3; write++
* ...
* write = 8;
* 1000 & 0111 = 0; write++
* write = 9;
* 1001 & 0111 = 1; write++
* ...
*
* Pop:
* read = 0;
* 0000 & 0111 = 0; read++ (读取缓冲队列的第0位置的数据)
* read = 1;
* 0001 & 0111 = 1; read++ (读取缓冲队列的第1位置的数据)
* read = 2;
* 0010 & 0111 = 2; read++
* read = 3
* 0011 & 0111 = 3; read++
* ...
* read = 8;
* 1000 & 0111 = 0; read++
* ...
* */ bool Push(T *type){ if(NULL == type){ return false;
}
//当条件不满足的时候,说明缓冲区已满,Push进来的数据就会丢失
if(_write < _read + _size){
//我们这里存入的是type指针,这个指针指向了一个我们分配的内存空间或者类
_queue[_write & _mask] = type;
_write++;
return true;
} return false;
} T *Pop(){ T *tmp = NULL;
//当条件不满足的时候说明缓冲区已经没有数据
if(_read < _write){
//取出队列的数据
tmp = _queue[_read & _mask];
_read++;
} return tmp;
} int GetRemainSize(){ return (_write - _read);
}
};
下面是简单的测试代码:
//main.cpp #include <iostream>
#include <pthread.h>
#include "CRecycleQueue.h"
using namespace std; class UserInfo{ private :
int _num; public:
UserInfo(int num){ _num = num;
} int getUserNum(){ return _num;
}
}; CRecycleQueue<UserInfo> *queue = new CRecycleQueue<UserInfo>; void *write_func(void *args){ int num = ;
while(){ //UserInfo里可以封装你自己想要的数据
//这里仅仅是一个简单的测试用例
UserInfo *info = new UserInfo(num++); if(!queue->Push(info)){
//Push失败 删除手动分配的内存空间
delete info;
}
sleep();
}
} void *read_func(void *args){ while(){ UserInfo *info = NULL;
if(info = queue->Pop()){ cout<<info->getUserNum()<<endl;
delete info;
}
sleep();
}
}
int
main(){ queue->InitRecycleQueue(); pthread_t pid1;
pthread_t pid2;
//这种生产者和消费者都只有一个的情况下,这个循环缓冲区为竞争问题提供了免锁,大大提高了程序的处理效率
pthread_create(&pid1,NULL,read_func,NULL);
pthread_create(&pid2,NULL,write_func,NULL); pthread_join(pid1,NULL);
pthread_join(pid2,NULL); return ;
}
编译:g++ main.cpp -lpthread -o test
这个循环缓冲队列大体的功能已经实现,其中循环缓冲队列一些其他操作并没有去实现,只是描述了一些核心的操作!
如果有错误和其他意见,提出来大家一起相互讨论和学习!
linux c++循环缓冲区模板类的更多相关文章
- 24小时学通Linux内核--内核探索工具类
寒假闲下来了,可以尽情的做自己喜欢的事情,专心待在实验室里燥起来了,因为大二的时候接触过Linux,只是关于内核方面确实是不好懂,所以十天的时间里还是希望能够补充一下Linux内核相关知识,接下来继续 ...
- 单链表的C++实现(采用模板类)
采用模板类实现的好处是,不用拘泥于特定的数据类型.就像活字印刷术,制定好模板,就可以批量印刷,比手抄要强多少倍! 此处不具体介绍泛型编程,还是着重叙述链表的定义和相关操作. 链表结构定义 定义单链表 ...
- C++11特性(模板类 initializer_list)
[1]initializer_list模板类 C++primer 原文如下: 通读原文相关篇幅,分析解读内容如下: 提供initializer_list类的初衷,为了便于将有限个同一类型(或可转换为同 ...
- 高效的两段式循环缓冲区──BipBuffer
Simon Cooke,美国 (原作者) 北京理工大学 20981 陈罡(翻译) 写在前面的话: 循环缓冲区是一个非常常用的数据存储结构,已经被广泛地用于连续.流数据的存储和通信应用中.对于循环缓冲区 ...
- 7.2 C++模板类实例化
参考:http://www.weixueyuan.net/view/6399.html 总结: array < int >表明用int类型来代替模板类中的类参数“T”,编译器会将模板类ar ...
- C++模板类练习题
题目说明: 编写一个程序,使用类模板对数组元素进行排序,倒置.查找和求和 具有对数组元素进行排序,倒置.查找和求和功能, 然后产生类型实参分别为int型和double型的两个模板类, 分别对整型数组与 ...
- 027_编写MapReduce的模板类Mapper、Reducer和Driver
模板类编写好后写MapReduce程序,的模板类编写好以后只需要改参数就行了,代码如下: package org.dragon.hadoop.mr.module; import java.io.IOE ...
- 学艺不精而惭愧--论C++模板类的使用
自己断断续续地使用C++也有一段时间了.有些时候产生了自满的情绪.觉得自己对C++的语言特性已经知道的几乎相同了,在语法方面没有什么难倒我的地方了,如今所要做的是依据实际问题编敲代码,问题的难点在于算 ...
- 模板类 error LNK2019: 无法解析的外部符号
如果将类模板的声明和实现写在两个独立的文件中,在构建时会出现"error LNK2019: 无法解析的外部符号 "的错误. 解决方法有: 第一种方法,就是把类模板中成员函数的声明和 ...
随机推荐
- 写了好多次SSH现在对于框架还是有一定的基础了,但是对于框架下我们该如何进行操作呢???
首先,对于一个老手来说,我们最快捷的就是ctrl+c和ctrl+v,但是我们自己应该复制哪一些代码呢? 1.在我们导完包之后,我们需要写的就是web.xml,在其中,我们要有过滤器及映射和监听器. w ...
- Types of Learning
从四个角度大致总结一下不同类型的机器学习问题. 1. 按照输出空间的变化: 分类问题(二分类.多分类).回归问题 2. 按照输出的标记变化: 监督学习 与 非监督学习 与 半监督学习(树的识别) 与 ...
- Linux SSH,FTP服务配置
CentOS-6.4-x86_64-minimal 0.网卡配置 参考:Linux系统\Centos没有网卡eth0配置文件怎么办? - http://jingyan.baidu.com/articl ...
- JSP开发模式2_JSP/Servlet/JavaBean(简单注册功能)
import java.util.regex.Matcher;import java.util.regex.Pattern; public class RegisterBean { privat ...
- OAuth 2.0 Threat Model and Security Considerations (rfc6819)
Authorization server The following data elements are stored or accessible on the authorization serve ...
- JavaWeb---设置content-disposition响应头,让浏览器下载文件
package com.zyz; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServlet ...
- iOS Core Animation之CALayer心得
使用CALayer的mask实现注水动画效果 Core Animation一直是iOS比较有意思的一个主题,使用Core Animation可以实现非常平滑的炫酷动画.Core animtion的AP ...
- WIN7环境下CUDA7.5的安装、配置和测试(Visual Studio 2010)
以下基于"WIN7(64位)+Visual Studio 2010+CUDA7.5". 系统:WIN7,64位 开发平台:Visual Studio 2010 显卡:NVIDIA ...
- servlet的session为null?
servlet的session(会话)显示为null,一般是web.xml中配置不对或者在浏览器输入的url不正确造成的. web.xml配置如下: <servlet> <servl ...
- 根据UIColor对象,获取对应的RGBA值
- (NSArray *)getRGBWithColor:(UIColor *)color { CGFloat red = 0.0; CGFloat green = 0.0; CGFloat blue ...