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: 无法解析的外部符号 "的错误. 解决方法有: 第一种方法,就是把类模板中成员函数的声明和 ...
随机推荐
- 使用Linux碎解一
一.安装VMwarestation. 二.安装Linux系统(这里是CentOS7) 步骤: #==========================part1===================== ...
- js中原型继承的概念
- 关于使用READ TABLE语句的几点注意事项
原文地址 http://www.dlsap.com/thread-34-1-1.html 1. 如果使用READ TABLE语句来读取内部表数据,而不是简单看返回值判断是否存在,那么在使用REA ...
- 签名 cd
http://blog.sina.com.cn/s/blog_618199e60101uc7w.html
- js算出生日是当年第多少天
var year, month, day, monthSum = 0; var arr = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, ...
- js鼠标经过文字滚动,移开还原
不说别的,直接贴代码. <div class="kj-scroll" id="countrylist0" onmouseover="wPAa = ...
- MYSQL-5.5二进制包安装
groupadd mysql 添加用户组 useradd mysql -s /sbin/nologin -g mysql -M 添加用户 mv mysql-5.5.54-linux2.6-x86_6 ...
- js中常用的操作
1.js中常用的数组操作 2.js中常用的字符串操作 3.js中常用的时间日期操作 4.定时器
- Java C# C语言中的占位符
一般拼接一段字符串在编程中是很常见的事,下面简单做个总结: 什么是占位符?占位符就是先占住一个固定的位置,等着你再往里面添加内容的符号. 1.Java中处理方法: package com.amos; ...
- Android开发学习---android下的数据持久化,保存数据到rom文件,android_data目录下文件访问的权限控制
一.需求 做一个类似QQ登录似的app,将数据写到ROM文件里,并对数据进行回显. 二.截图 登录界面: 文件浏览器,查看文件的保存路径:/data/data/com.amos.datasave/fi ...