转载

linux c++循环缓冲区模板类

一:概述

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

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

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

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

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

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

正文到此结束
Loading...