未加星标

Linux C++循环缓冲区模板类

字体大小 | |
[系统(linux) 所属分类 系统(linux) | 发布者 店小二03 | 时间 20160901 | 作者 红领巾 ] 0人收藏点击收藏

一:概述

实际学习和工作中,我们经常会遇到读写大量数据的情况,这个时候我们可能就用到了循环缓冲区。

循环缓冲区在处理大量数据的时候有很大的优点,循环缓冲区在一些竞争问题上提供了一种免锁的机制,免锁的前提是,生产者和消费都只有一个的情况下,否则也要加锁。

二:循环缓冲区的实现理论如下图

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 = 0;
_write = 0;
_size = 0;
_mask = 0;
}
//初始化循环缓冲区
bool InitRecycleQueue(int exp){

if(0 > exp){
return false;
}
_read = 0;
_write = 0;
//传进来一个整数,对1进行位移操作
//比如exp = 4
//_size的二进制表示:1000
_size = 1 << exp;
//_mask的二进制表示:0111
_mask = _size - 1;
//分配缓冲区空间
_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 = 0;
while(1){
//UserInfo里可以封装你自己想要的数据
//这里仅仅是一个简单的测试用例
UserInfo *info = new UserInfo(num++);
if(!queue->Push(info)){
//Push失败 删除手动分配的内存空间
delete info;
}
sleep(1);
}
}

void *read_func(void *args){

while(1){

UserInfo *info = NULL;
if(info = queue->Pop()){
cout<<info->getUserNum()<<endl;
delete info;
}
sleep(1);
}
}
int
main(){

queue->InitRecycleQueue(8);

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 0;
}

编译:g++ main.cpp -lpthread -o test

这个循环缓冲队列大体的功能已经实现,其中循环缓冲队列一些其他操作并没有去实现,只是描述了一些核心的操作!

如果有错误和其他意见,提出来大家一起相互讨论和学习!

本文地址:http://www.linuxidc.com/Linux/2016-09/135458.htm


Linux C++循环缓冲区模板类

本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统

主题: LinuxC++数据消费理大删除变量
分页:12
转载请注明
本文标题:Linux C++循环缓冲区模板类
本站链接:http://www.codesec.net/view/483453.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 系统(linux) | 评论(0) | 阅读(22)