C++ 环形缓冲区的实现
参考文章:http://blog.csdn.net/linyt/article/details/53355355
本文参考linux系统中 kfifo缓冲区实现.由于没有涉及到锁,在多线程环境下,只适用于 单生产者 + 单消费者 模型.
fifo_buffer.h
#ifndef FIFO_BUFFER_H_
#define FIFO_BUFFER_H_
#include <stdint.h> class FifoBuffer
{
public:
enum
{
enmDefaultBufferLen = ,
};
public:
FifoBuffer(const uint32_t size = enmDefaultBufferLen);
~FifoBuffer();
public:
uint32_t Put(const char *buf, const uint32_t bufLen);
uint32_t Get(char buf[], const uint32_t maxBufLen);
uint32_t Size(){ return size; }
uint32_t EmptySize();
uint32_t UsedSize();
const char *Buffer(){ return buffer; }
private:
uint32_t Min(uint32_t left, uint32_t right){ return left > right ? right : left; }
private:
uint32_t size;
volatile uint32_t in;
volatile uint32_t out;
char *buffer;
};
#endif
fifo_buffer.cpp
#include <malloc.h>
#include <new>
#include <algorithm>
#include "fifo_buffer.h" //////////////////////////////////////////////////////////////////////////
// when out < in
// | |
// |----------------------------------------|
// 0 out|~~~~~~~~~~|in size
//////////////////////////////////////////////////////////////////////////
// when out > in
// | |
// |----------------------------------------|
// 0~~~~~~~|in out|~~~~~~~~~~~~~~~~~~size
////////////////////////////////////////////////////////////////////////// FifoBuffer::FifoBuffer(const uint32_t size /*= enmDefaultBufferLen*/) :in(), out(), size()
{
buffer = new (std::nothrow) char[size];
if (!buffer){ return; }
memset(buffer, , size);
this->size = size;
} FifoBuffer::~FifoBuffer()
{
if (buffer)
{
delete[] buffer;
}
} uint32_t FifoBuffer::Put(const char *buf, const uint32_t bufLen)
{
uint32_t lengthToPut = Min(bufLen, EmptySize());
/* first put the data starting from fifo->in to buffer end */
uint32_t len = Min(lengthToPut, size - (in % size));
memcpy(buffer + (in % size), buf, len);
/* then put the rest (if any) at the beginning of the buffer */
memcpy(buffer, buf + len, lengthToPut - len);
in += lengthToPut;
return lengthToPut;
} uint32_t FifoBuffer::Get(char buf[], const uint32_t maxBufLen)
{
uint32_t lengthToGet = Min(maxBufLen, UsedSize());
/* first get the data from fifo->out until the end of the buffer */
uint32_t len = Min(lengthToGet, size - (out % size));
memcpy(buf, buffer + (out % size), len);
/* then get the rest (if any) from the beginning of the buffer */
memcpy(buf + len, buffer, lengthToGet - len);
out += lengthToGet;
return lengthToGet;
} uint32_t FifoBuffer::EmptySize()
{
return size - in + out;
} uint32_t FifoBuffer::UsedSize()
{
return in - out;
}
测试代码:
#include <stdio.h>
#include <fstream>
#include <windows.h>
#include <thread> #include "fifo_buffer.h"
const char *fileName = "data.txt";
enum
{
enummaxBufLen = ,
}; void WriteToFile(const char *fileName, const char *buf, const uint32_t bufLen);
void ReadFromFile(const char *fileName, char buf[], const uint32_t maxBufLen);
void GenTestFile(); void PutSomeBytes(const char *oriBuf, const uint32_t bufLen, FifoBuffer &fifoBuf);
void GetSomeBytes(FifoBuffer &fifoBuf, char buf[], const uint32_t maxBufLen); int32_t main()
{
GenTestFile();
FifoBuffer fifoBuf(enummaxBufLen + );
char *oriBuf = new char[enummaxBufLen + ];
char *putBuf = new char[enummaxBufLen + ];
memset(oriBuf, , enummaxBufLen + );
memset(putBuf, , enummaxBufLen + );
ReadFromFile(fileName, oriBuf, enummaxBufLen);
//////////////////////////////////////////////////////////////////////////
std::thread put(PutSomeBytes, oriBuf, enummaxBufLen, std::ref(fifoBuf)); std::thread get(GetSomeBytes, std::ref(fifoBuf), putBuf, enummaxBufLen); put.join();
get.join(); printf("%s\n%d\n\n", fifoBuf.Buffer(), strlen(fifoBuf.Buffer())); printf("%s\n%d\n\n", putBuf, strlen(putBuf));
system("pause");
} void WriteToFile(const char *fileName, const char *buf, const uint32_t bufLen)
{
std::ofstream outFile(fileName, std::ios::out);
if (!outFile){ return; }
outFile.write(buf, bufLen);
outFile.close();
} void ReadFromFile(const char *fileName, char buf[], const uint32_t maxBufLen)
{
std::ifstream inFile(fileName, std::ios::in);
if (!inFile){ return; }
inFile.read(buf, maxBufLen);
inFile.close();
} void GenTestFile()
{
char *buf = new char[enummaxBufLen];
for (uint32_t i = ; i < enummaxBufLen; ++i)
{
buf[i] = i % + '';
}
WriteToFile(fileName, buf, enummaxBufLen);
delete[] buf;
} void PutSomeBytes(const char *oriBuf, const uint32_t bufLen, FifoBuffer &fifoBuf)
{
static uint32_t offset = ;
while (offset < bufLen)
{
int32_t byteCount = rand() % ;
offset += fifoBuf.Put(oriBuf + offset, byteCount);
Sleep();
}
} void GetSomeBytes(FifoBuffer &fifoBuf, char buf[], const uint32_t maxBufLen)
{
static uint32_t offset = ;
while (offset < maxBufLen)
{
int32_t byteCount = rand() % ;
offset += fifoBuf.Get(buf + offset, byteCount);
}
}
C++ 环形缓冲区的实现的更多相关文章
- linux device driver —— 环形缓冲区的实现
还是没有接触到怎么控制硬件,但是在书里看到了一个挺巧妙的环形缓冲区实现. 此环形缓冲区实际为一个大小为bufsize的一维数组,有一个rp的读指针,一个wp的写指针. 在数据满时写进程会等待读进程读取 ...
- 35.Linux-分析并制作环形缓冲区
在上章34.Linux-printk分析.使用printk调试驱动里讲述了: printk()会将打印信息存在内核的环形缓冲区log_buf[]里, 可以通过dmesg命令来查看log_buf[] 1 ...
- input子系统事件处理层(evdev)的环形缓冲区【转】
在事件处理层(evdev.c)中结构体evdev_client定义了一个环形缓冲区(circular buffer),其原理是用数组的方式实现了一个先进先出的循环队列(circular queue), ...
- 环形缓冲区-模仿linux kfifo【转】
转自:https://blog.csdn.net/vertor11/article/details/53741681 struct kfifo{ uint8_t *buffer; uint32_t i ...
- linux网络编程--Circular Buffer(Ring Buffer) 环形缓冲区的设计与实现【转】
转自:https://blog.csdn.net/yusiguyuan/article/details/18368095 1. 应用场景 网络编程中有这样一种场景:需要应用程序代码一边从TCP/IP协 ...
- linux下C语言实现多线程通信—环形缓冲区,可用于生产者(producer)/消费者(consumer)【转】
转自:http://blog.chinaunix.net/uid-28458801-id-4262445.html 操作系统:ubuntu10.04 前言: 在嵌入式开发中,只要是带操作系统的 ...
- STM32进阶之串口环形缓冲区实现(转载)
转载自微信公众号“玩转单片机”,感谢原作者“杰杰”. 队列的概念 在此之前,我们来回顾一下队列的基本概念:队列 (Queue):是一种先进先出(First In First Out ,简称 FIFO) ...
- 嵌入式框架Zorb Framework搭建二:环形缓冲区的实现
我是卓波,我是一名嵌入式工程师,我万万没想到我会在这里跟大家吹牛皮. 嵌入式框架Zorb Framework搭建过程 嵌入式框架Zorb Framework搭建一:嵌入式环境搭建.调试输出和建立时间系 ...
- 环形缓冲区的应用ringbuffer
在嵌入式开发中离不开设备通信,而在通信中稳定性最高的莫过于环形缓冲区算法, 当读取速度大于写入速度时,在环形缓冲区的支持下不会丢掉任何一个字节(硬件问题除外). 在通信程序中,经常使用环形缓冲区作为数 ...
- 环形缓冲区实现类(Delphi)
环形缓冲区的用途及原理可以去百度资料狠多的,这里就不介绍了.直接贴代码.代码分别用D7,XE2编译测试 源码下载 http://files.cnblogs.com/lwm8246/uCircleBuf ...
随机推荐
- 【安装MongoDB】CentOS7 下安装NodeJs+Express+MongoDB+Redis
MongoDB,V3.2版本,官网说的很详细,见链接:https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/ 1.创建 ...
- ASM:《X86汇编语言-从实模式到保护模式》第9章:实模式下中断机制和实时时钟
中断是处理器一个非常重要的工作机制.第9章是讲中断在实模式下如何工作,第17章是讲中断在保护模式下如何工作. ★PART1:外部硬件中断 外部硬件中断是通过两个信号线引入处理器内部的,这两条线分别叫N ...
- NEFU 561 方块计算
题目链接 简单搜索题 #include <cstdio> #include <iostream> #include <cstring> using namespac ...
- jasig CAS 实现单点登录 - java、php客户端登录实现
jasig CAS项目本身就是一个完整的CAS单点登录服务 1.服务端需要把 认证处理类.用户属性返回值处理类 调整成我们自己处理类即可实现单点登录 2.java客户端需要引入cas-client- ...
- C++ 基础知识复习(二)
异常处理部分: 23. 在c++的异常处理中,除了提供异常的关键字语法支持以外,其标准库中支持异常处理而封装异常类也很好的为应用程序中异常处理判断使用提供直接的帮助.C++语言中针对异常处理提供了三个 ...
- Unity4.0的使用
最近公司用到了Unity,自己就研究了一下. 新建一个ASP.NET MVC基本项目,在NuGet上引入Unity4.0.1最新版. 因为我使用的项目为ASP.NET MVC,所以又添加一个Unity ...
- 【转】oracle 中随机取一条记录的两种方法
oracle 中随机取一条记录的两种方法 V_COUNT INT:=0; V_NUM INT :=0; 1:TBL_MYTABLE 表中要有一个值连续且唯一的列FID BEGIN SELECT COU ...
- 从零开始山寨Caffe·贰:主存模型
你左手是内存,右手是显存,内存可以打死显存,显存也可以打死内存. —— 请协调好你的主存 从硬件说起 物理之觞 大部分Caffe源码解读都喜欢跳过这部分,我不知道他们是什么心态,因为这恰恰是最重要的一 ...
- React-Native android在windows下的踩坑记
坑很多,跳之前做好准备.没有VPN的同学请浏览完本文后慎行. 你需要先安装最新版本的node.js(我最后使用的是v4.1.2),前往官网下载>> 注:我win7已经安装过Visual ...
- oracle 数据库 时间差 年数、月数、天数、小时数、分钟数、秒数
declare l_start date := to_date('2015-04-29 01:02:03', 'yyyy-mm-dd hh24:mi:ss'); l_end date := to_da ...