zoukankan      html  css  js  c++  java
  • 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 = 1024,
        };
    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(0), out(0), size(0)
    {
        buffer = new (std::nothrow) char[size];
        if (!buffer){ return; }
        memset(buffer, 0, 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 = 10243,
    };
    
    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 + 1);
        char *oriBuf = new char[enummaxBufLen + 1];
        char *putBuf = new char[enummaxBufLen + 1];
        memset(oriBuf, 0, enummaxBufLen + 1);
        memset(putBuf, 0, enummaxBufLen + 1);
        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
    %d
    
    ", fifoBuf.Buffer(), strlen(fifoBuf.Buffer()));
    
        printf("%s
    %d
    
    ", 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 = 0; i < enummaxBufLen; ++i)
        {
            buf[i] = i % 10 + '0';
        }
        WriteToFile(fileName, buf, enummaxBufLen);
        delete[] buf;
    }
    
    void PutSomeBytes(const char *oriBuf, const uint32_t bufLen, FifoBuffer &fifoBuf)
    {
        static uint32_t offset = 0;
        while (offset < bufLen)
        {
            int32_t byteCount = rand() % 3;
            offset += fifoBuf.Put(oriBuf + offset, byteCount);
            Sleep(1);
        }
    }
    
    void GetSomeBytes(FifoBuffer &fifoBuf, char buf[], const uint32_t maxBufLen)
    {
        static uint32_t offset = 0;
        while (offset < maxBufLen)
        {
            int32_t byteCount = rand() % 3;
            offset += fifoBuf.Get(buf + offset, byteCount);
        }
    }
  • 相关阅读:
    PHP获取今天、昨天、明天的日期
    PHP使用Apache中的ab测试网站的压力性能
    php 数组操作
    ajax实时获取下拉数据
    php微信支付测试开发(流程已通)
    微信支付调用JSAPI缺少参数:timeStamp
    JS dom最常用API
    Javascript刷新页面的几种方法
    php+mysql 安全
    隐式的类类型转换
  • 原文地址:https://www.cnblogs.com/tangxin-blog/p/6131952.html
Copyright © 2011-2022 走看看