博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ring buffer 亲测好用 C++ 11
阅读量:4576 次
发布时间:2019-06-08

本文共 10908 字,大约阅读时间需要 36 分钟。

头文件

#pragma once#include 
//#include
class CCycleBuffer{public: bool isFull(); bool isEmpty(); void empty(); int getReadableLength(); int getWriteableLength(); CCycleBuffer(int size); virtual~CCycleBuffer(); int write(char* buf, int count); int read(char* buf, int count); int getStart() { return m_nReadPos; } int getEnd() { return m_nWritePos; }private: std::atomic_bool m_bEmpty, m_bFull; char* m_pBuf; int m_nBufSize; std::atomic_int m_nReadPos; std::atomic_int m_nWritePos; //std::mutex m_mutex; int test;};

cpp文件

#include "CCycleBuffer.h"#include 
#include
// 定义 CCycleBuffer::CCycleBuffer(int size){ m_nBufSize = size; m_nReadPos = 0; m_nWritePos = 0; m_pBuf = new char[m_nBufSize]; m_bEmpty = true; m_bFull = false; test = 0;}CCycleBuffer::~CCycleBuffer(){ delete[] m_pBuf;}/************************************************************************//* 向缓冲区写入数据,返回实际写入的字节数 *//************************************************************************/int CCycleBuffer::write(char* buf, int count){ std::atomic_int m_nReadPos; m_nReadPos = (int)this->m_nReadPos; if (count <= 0) return 0; // 缓冲区已满,不能继续写入 if (m_bFull) { return 0; } else if (m_nReadPos == m_nWritePos)// 缓冲区为空时 { /* == 内存模型 == |← m_nBufSize →| |← (empty)→ ← (empty) →| |------------||------------------------------| ↑← leftcount →| m_nReadPos m_nWritePos */ int leftcount = m_nBufSize - m_nWritePos; if (leftcount > count) { memcpy(m_pBuf + m_nWritePos, buf, count); //m_mutex.lock(); m_nWritePos += count; m_bFull = (this->m_nReadPos == m_nWritePos); //m_mutex.unlock(); m_bEmpty = false; return count; } else { std::atomic_int tmp; int leftcount2=0; memcpy(m_pBuf + m_nWritePos, buf, leftcount); tmp = count - leftcount; leftcount2 = (m_nReadPos > tmp) ? tmp : m_nReadPos; memcpy(m_pBuf, buf + leftcount, leftcount2); //m_mutex.lock(); m_nWritePos = leftcount2; m_bFull = (this->m_nReadPos == m_nWritePos); //m_mutex.unlock(); m_bEmpty = false; return leftcount + m_nWritePos; } } else if (m_nReadPos < m_nWritePos)// 有剩余空间可写入 { /* == 内存模型 == |← m_nBufSize →| |← (empty)→ ← (data) → ← (empty) →| |------------||xxxxxxxxxxxxx||---------------| ↑ ↑← leftcount →| m_nReadPos m_nWritePos */ // 剩余缓冲区大小(从写入位置到缓冲区尾) int leftcount = m_nBufSize - m_nWritePos; int test = m_nWritePos; if (leftcount > count) // 有足够的剩余空间存放 { memcpy(m_pBuf + m_nWritePos, buf, count); //m_mutex.lock(); m_nWritePos += count; m_bFull = (this->m_nReadPos == m_nWritePos); //m_mutex.unlock(); m_bEmpty = false; return count; } else // 剩余空间不足 { // 先填充满剩余空间,再回头找空间存放 std::atomic_int tmp; int leftcount2=0; memcpy(m_pBuf + test, buf, leftcount); tmp = count - leftcount; leftcount2 = (m_nReadPos > tmp) ? tmp : m_nReadPos; memcpy(m_pBuf, buf + leftcount, leftcount2); //m_mutex.lock(); m_nWritePos = leftcount2; m_bFull = (this->m_nReadPos == m_nWritePos); //m_mutex.unlock(); m_bEmpty = false; return leftcount + m_nWritePos; } } else { /* == 内存模型 == |← m_nBufSize →| |← (data) → ← (empty) → ← (data) →| |xxxxxxxxxxxx||---------------||xxxxxxxxxxxxxxx| | ↑← leftcount →↑ | m_nWritePos m_nReadPos */ int leftcount = m_nReadPos - m_nWritePos; if (leftcount > count) { // 有足够的剩余空间存放 memcpy(m_pBuf + m_nWritePos, buf, count); //m_mutex.lock(); m_nWritePos += count; m_bFull = (this->m_nReadPos == m_nWritePos); //m_mutex.unlock(); m_bEmpty = false; return count; } else { // 剩余空间不足时要丢弃后面的数据 memcpy(m_pBuf + m_nWritePos, buf, leftcount); //m_mutex.lock(); m_nWritePos += leftcount; m_bFull = (this->m_nReadPos == m_nWritePos); //m_mutex.unlock(); m_bEmpty = false; return leftcount; } }}/************************************************************************//* 从缓冲区读数据,返回实际读取的字节数 *//************************************************************************/int CCycleBuffer::read(char* buf, int count){ std::atomic_int m_nWritePos; m_nWritePos = (int)this->m_nWritePos; if (count <= 0) return 0; //m_bFull = false; if (m_bEmpty) // 缓冲区空,不能继续读取数据 { return 0; } else if (m_nReadPos == m_nWritePos) // 缓冲区满时 { /* == 内存模型 == |← m_nBufSize →| |← (data) → ← (data) →| |xxxxxxxxxxxx||xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| | ↑← leftcount →| m_nWritePos m_nReadPos */ int leftcount = m_nBufSize - m_nReadPos; if (leftcount > count) { memcpy(buf, m_pBuf + m_nReadPos, count); //m_mutex.lock(); m_nReadPos += count; m_bEmpty = (m_nReadPos == this->m_nWritePos); //m_mutex.unlock(); m_bFull = false; return count; } else { std::atomic_int tmp; int leftcount2; memcpy(buf, m_pBuf + m_nReadPos, leftcount); tmp = count - leftcount; leftcount2 = (m_nWritePos > tmp) ? tmp : m_nWritePos; memcpy(buf + leftcount, m_pBuf, leftcount2); //m_mutex.lock(); m_nReadPos = leftcount2; m_bEmpty = (m_nReadPos == this->m_nWritePos); //m_mutex.unlock(); m_bFull = false; return leftcount + m_nReadPos; } } else if (m_nReadPos < m_nWritePos) // 写指针在前(未读数据是连接的) { /* == 内存模型 == |← m_nBufSize →| |← (empty)→ ← (data) → ← (empty) →| |------------||xxxxxxxxxxxxxxx||---------------| ↑← leftcount →↑ | m_nReadPos m_nWritePos */ int leftcount = m_nWritePos - m_nReadPos; int c = (leftcount > count) ? count : leftcount; memcpy(buf, m_pBuf + m_nReadPos, c); //m_mutex.lock(); m_nReadPos += c; m_bEmpty = (m_nReadPos == this->m_nWritePos); //m_mutex.unlock(); m_bFull = false; return c; } else // 读指针在前(未读数据可能是不连接的) { /* == 内存模型 == |← m_nBufSize →| |← (data) → ← (empty) → ← (data) →| |xxxxxxxxxxxx||---------------||xxxxxxxxxxxxxxx| | ↑ ↑← leftcount →| m_nWritePos m_nReadPos */ int leftcount = m_nBufSize - m_nReadPos; if (leftcount > count) // 未读缓冲区够大,直接读取数据 { memcpy(buf, m_pBuf + m_nReadPos, count); //m_mutex.lock(); m_nReadPos += count; m_bEmpty = (m_nReadPos == this->m_nWritePos); //m_mutex.unlock(); m_bFull = false; return count; } else // 未读缓冲区不足,需回到缓冲区头开始读 { memcpy(buf, m_pBuf + m_nReadPos, leftcount); std::atomic_int tmp; int leftcount2; tmp = count - leftcount; leftcount2 = (m_nWritePos > tmp) ? tmp : m_nWritePos; memcpy(buf + leftcount, m_pBuf, leftcount2); //m_mutex.lock(); m_nReadPos = leftcount2; m_bEmpty = (m_nReadPos == this->m_nWritePos); //m_mutex.unlock(); m_bFull = false; return leftcount + m_nReadPos; } }}/************************************************************************//* 获取缓冲区有效数据长度 *//************************************************************************/int CCycleBuffer::getReadableLength(){ if (m_bEmpty) { return 0; } else if (m_bFull) { return m_nBufSize; } else if (m_nReadPos < m_nWritePos) { return m_nWritePos - m_nReadPos; } else { return m_nBufSize - m_nReadPos + m_nWritePos; }}int CCycleBuffer::getWriteableLength(){ return m_nBufSize-getReadableLength();}void CCycleBuffer::empty(){ m_nReadPos = 0; m_nWritePos = 0; m_bEmpty = true; m_bFull = false;}bool CCycleBuffer::isEmpty(){ return m_bEmpty;}bool CCycleBuffer::isFull(){ return m_bFull;}

main函数

#include 
// std::cout#include
// std::thread#include
// std::mutex, std::unique_lock#include
// std::condition_variable#include
#include "CCycleBuffer.h"//#define TESTTHREAD #define TESTRINGBUF#ifdef TESTTHREADstd::mutex mtx; // 全局互斥锁.std::condition_variable cv; // 全局条件变量.bool ready = false; // 全局标志位.#endifCCycleBuffer rbuf(10);char buf[] = "123456";char buf4r[6] = { 0 };int main(){ std::cout<<"begin main..."<
lck(mtx); //while (!ready) // 如果标志位不为 true, 则等待... cv.wait(lck); // 当前线程被阻塞, 当全局标志位变为 true 之后, // 线程被唤醒, 继续往下执行打印线程编号id. std::cout << "thread " << id << '\n'; },i); } std::cout << "10 threads ready to race...\n"; std::unique_lock
lck(mtx); ready = true; // 设置全局标志位为 true. cv.notify_all(); // 唤醒所有线程. for (auto & th : threads) th->join();#endif#ifdef TESTRINGBUF int ret; std::thread* threads[2]; //bzero(buf4r,sizeof(buf4r)); //ret = rbuf.getWriteableLength(); //ret = rbuf.write(buf,4); //ret = rbuf.read(buf4r,2); threads[0] = new std::thread([]() { std::cout<<"begin write thread ..."<
join(); } //getchar(); return 0;}

 

posted on
2018-12-16 23:15 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/liuguoyao514257665/p/10129108.html

你可能感兴趣的文章
uva 12003 Array Transformer (大规模阵列)
查看>>
mysql5.7二进制包安装方式
查看>>
装饰者模式——Java设计模式
查看>>
39.递推练习: 菲波那契数列(2)
查看>>
排序精讲
查看>>
【bzoj3172】 Tjoi2013—单词
查看>>
【uoj2】 NOI2014—起床困难综合症
查看>>
js return的用法
查看>>
子节点填充父元素除去一固定高度后的剩余高度
查看>>
[原]IOS 后台发送邮件
查看>>
(转)JAVA Calendar详解
查看>>
转: 编码,charset,乱码,unicode,utf-8与net简单释义
查看>>
C#--正则匹配
查看>>
5.30 考试修改+总结
查看>>
BA-设计施工调试流程
查看>>
C#-CLR各版本特点
查看>>
css3背景透明文字不透明
查看>>
《java JDK7 学习笔记》之接口与多态
查看>>
LeetCode 96:Unique Binary Search Trees
查看>>
kernel-char设备的建立
查看>>