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: 无法解析的外部符号 "的错误. 解决方法有: 第一种方法,就是把类模板中成员函数的声明和 ...
随机推荐
- MYBATIS 文档
http://www.mybatis.org/mybatis-3/zh/index.html
- 我的VPN推荐经历
先说说我为什么会走上VPN推荐之路的. 忘记了什么原因需要上某一国外的网站,但是这个网站在国内被禁止访问,于是我想到了VPN,我在网上搜索VPN,找到了几个VPN推荐的博客,然后我根据博客的推荐到了某 ...
- Android Dex文件格式(二)
第三块: 数据区 索引区中的最终数据偏移以及文件头中描述的map_off偏移都指向数据区, 还包括了即将要解析的class_def_item, 这个结构非常重要,下面就开始解析 c ...
- 破解excel密码保护
破解excel密码保护 录制一个新宏.内容如下.保存后运行,点几次确定,过一分钟还会再弹出来,再点确定,然后就好了. Public Sub AllInternalPasswords() ' Break ...
- python 2.4 与 python 3.0 的比较
转过来,留着日后查看 [转自:]http://hi.baidu.com/autoitcn/blog/item/5f41973294b5fc4fac4b5f77.html python 2.4 与 py ...
- dojo grid 编辑问题
今天dojo grid编辑小问题,找了半天才找到问题, 1.问题 2.原因 数据单元没有索引列->id 3.修改前代码 <!DOCTYPE HTML> <html lang=& ...
- HFSS设计导入AD中
具体过程有些繁琐,录制了一个视频放在百度网盘了.亲测有效. 网盘地址:http://pan.baidu.com/s/1gfIBhC3 密码:ayoa
- matlab 连续读取多个文件
方法1: 把文件的文件名按一定的规律命名,假如:filename1.txt,filename2.txt,...,fielname100.txt,在读取的时候则可以使用循环: for i = 1:100 ...
- JSON Object(如NSDictionary,NSArray)转化为JSON格式的NSString #iOS开发
NSString *string = [self jsonObjectToJSONString:inputDataDic]; -(NSString*)jsonObjectToJSONString:(i ...
- C#多线程实现方法
C#中实现线程应用开发的类都包含在了System.Threading命名空间中,比较常用的是Thread,ThreadPool类 Thread类构造函数作用是创建线程,有两个重载版本,一个带参数,一个 ...