一:概述ios
實際學習和工做中,咱們常常會遇到讀寫大量數據的狀況,這個時候咱們可能就用到了循環緩衝區。學習
循環緩衝區在處理大量數據的時候有很大的優勢,循環緩衝區在一些競爭問題上提供了一種免鎖的機制,免鎖的前提是,生產者和消費都只有一個的狀況下,不然也要加鎖。測試
二:循環緩衝區的實現理論以下圖spa
三:實現代碼以下所示:3d
//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 testcode
這個循環緩衝隊列大致的功能已經實現,其中循環緩衝隊列一些其餘操做並無去實現,只是描述了一些核心的操做!blog
若是有錯誤和其餘意見,提出來你們一塊兒相互討論和學習!隊列