仿Muduo库实现高并发服务器——Buffer模块

news2024/9/23 4:19:45

        Buffer模块并没有什么复杂错误。

上图反应了下面代码的各种操作。

#define BUFFER_DEFAULT_SIZE 1024
class Buffer {
    private:
        std::vector<char> _buffer; //使用vector进行内存空间管理
        uint64_t _reader_idx; //读偏移
        uint64_t _writer_idx; //写偏移
    public:
        Buffer():_reader_idx(0), _writer_idx(0), _buffer(BUFFER_DEFAULT_SIZE){}
        char *Begin() { return &*_buffer.begin(); }
        //获取当前写入起始地址, _buffer的空间起始地址,加上写偏移量
        char *WritePosition() { return Begin() + _writer_idx; }
        //获取当前读取起始地址
        char *ReadPosition() { return Begin() + _reader_idx; }
        //获取缓冲区末尾空闲空间大小--写偏移之后的空闲空间, 总体空间大小减去写偏移
        uint64_t TailIdleSize() { return _buffer.size() - _writer_idx; }
        //获取缓冲区起始空闲空间大小--读偏移之前的空闲空间
        uint64_t HeadIdleSize() { return _reader_idx; }
        //获取可读数据大小 = 写偏移 - 读偏移
        uint64_t ReadAbleSize() { return _writer_idx - _reader_idx; }
        //将读偏移向后移动
        void MoveReadOffset(uint64_t len) { 
            if (len == 0) return; 
            //向后移动的大小,必须小于可读数据大小
            assert(len <= ReadAbleSize());
            _reader_idx += len;
        }
        //将写偏移向后移动 
        void MoveWriteOffset(uint64_t len) {
            //向后移动的大小,必须小于当前后边的空闲空间大小
            assert(len <= TailIdleSize());
            _writer_idx += len;
        }
        //确保可写空间足够(整体空闲空间够了就移动数据,否则就扩容)
        void EnsureWriteSpace(uint64_t len) {
            //如果末尾空闲空间大小足够,直接返回
            if (TailIdleSize() >= len) { return; }
            //末尾空闲空间不够,则判断加上起始位置的空闲空间大小是否足够, 够了就将数据移动到起始位置
            if (len <= TailIdleSize() + HeadIdleSize()) {
                //将数据移动到起始位置
                uint64_t rsz = ReadAbleSize();//把当前数据大小先保存起来
                std::copy(ReadPosition(), ReadPosition() + rsz, Begin());//把可读数据拷贝到起始位置
                _reader_idx = 0;    //将读偏移归0
                _writer_idx = rsz;  //将写位置置为可读数据大小, 因为当前的可读数据大小就是写偏移量
            }else {
                //总体空间不够,则需要扩容,不移动数据,直接给写偏移之后扩容足够空间即可
                DBG_LOG("RESIZE %ld", _writer_idx + len);
                _buffer.resize(_writer_idx + len);
            }
        } 
        //写入数据
        void Write(const void *data, uint64_t len) {
            //1. 保证有足够空间,2. 拷贝数据进去
            if (len == 0) return;
            EnsureWriteSpace(len);
            const char *d = (const char *)data;
            std::copy(d, d + len, WritePosition());
        }
        void WriteAndPush(const void *data, uint64_t len) {
            Write(data, len);
            MoveWriteOffset(len);
        }
        void WriteString(const std::string &data) {
            return Write(data.c_str(), data.size());
        }
        void WriteStringAndPush(const std::string &data) {
            WriteString(data);
            MoveWriteOffset(data.size());
        }
        void WriteBuffer(Buffer &data) {
            return Write(data.ReadPosition(), data.ReadAbleSize());
        }
        void WriteBufferAndPush(Buffer &data) { 
            WriteBuffer(data);
            MoveWriteOffset(data.ReadAbleSize());
        }
        //读取数据
        void Read(void *buf, uint64_t len) {
            //要求要获取的数据大小必须小于可读数据大小
            assert(len <= ReadAbleSize());
            std::copy(ReadPosition(), ReadPosition() + len, (char*)buf);
        }
        void ReadAndPop(void *buf, uint64_t len) {
            Read(buf, len);
            MoveReadOffset(len);
        }
        std::string ReadAsString(uint64_t len) {
            //要求要获取的数据大小必须小于可读数据大小
            assert(len <= ReadAbleSize());
            std::string str;
            str.resize(len);
            Read(&str[0], len);
            return str;
        }
        std::string ReadAsStringAndPop(uint64_t len) {
            assert(len <= ReadAbleSize());
            std::string str = ReadAsString(len);
            MoveReadOffset(len);
            return str;
        }
        char *FindCRLF() {
            char *res = (char*)memchr(ReadPosition(), '\n', ReadAbleSize());
            return res;
        }
        /*通常获取一行数据,这种情况针对是*/
        std::string GetLine() {
            char *pos = FindCRLF();
            if (pos == NULL) {
                return "";
            }
            // +1是为了把换行字符也取出来。
            return ReadAsString(pos - ReadPosition() + 1);
        }
        //获取一行数据
        std::string GetLineAndPop() {
            std::string str = GetLine();
            MoveReadOffset(str.size());
            return str;
        }
        //清空缓冲区
        void Clear() {
            //只需要将偏移量归0即可
            _reader_idx = 0;
            _writer_idx = 0;
        }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2034210.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu24.04、22.04或20.04安装Golang方法教程

在Ubuntu Linux&#xff08;例如 Ubuntu 24.04、22.04 或 20.04&#xff09;上安装Go&#xff08;Golang&#xff09;是一个简单的过程。我们可以使用默认系统存储库使用本教程中给出的命令下载开源 Go 编程语言&#xff0c;轻松构建简单、可靠和高效的软件。 Go语言由Google…

LoadRunner内置参数介绍

参数菜单 我用的是2023版本&#xff0c;每个版本的位置不一样&#xff0c;通常差不多&#xff0c;2种方式进入参数菜单 菜单栏进入参数 点击设计 - 参数 - 参数列表 脚本右键进入参数 选中你要参数化的内容&#xff0c;右键&#xff1a;使用参数替换 - 参数列表 参数列表 …

day16:一文弄懂函数对象、函数嵌套和函数闭包的关系和应用

1.函数的对象 精髓&#xff1a;可以把函数当成变量去用 1.1 可以赋值 # func内存地址 def func():print(from func)ffunc print(f,func) f()输出&#xff1a; <function func at 0x0000017A4E24F7F0> <function func at 0x0000017A4E24F7F0> from func 1.2 可以…

PythonStudio 控件使用常用方式(十四)TCheckListBox

PythonStudio是一个极强的开发Python的IDE工具&#xff0c;它使用的是Delphi的控件&#xff0c;常用的内容是与Delphi一致的。但是相关文档并一定完整。现在我试试能否逐步把它的控件常用用法写一点点&#xff0c;也作为PythonStudio的参考。 从1.2.1版开始&#xff0c;Python…

视频融合项目中的平台抉择:6大关键要素助力精准选型

随着安防监控系统行业的快速发展&#xff0c;视频融合项目逐渐成为城市治理、企业管理及智能建筑等领域的重要组成部分。视频融合平台作为视频数据整合、管理和分析的核心&#xff0c;其选择直接影响到项目的成功与否。 在当前智慧业务类项目的集成过程中&#xff0c;我们不仅…

漂亮网站是门面,和你的豪车、奢侈品、秘书一样,该投就得投。

对于企业来说&#xff0c;一个漂亮的网站可以起到很好的门面作用。一个好的网站可以让客户更容易地找到你的产品和服务&#xff0c;提高品牌形象和知名度&#xff0c;增加业务成功几率。因此&#xff0c;对于企业来说&#xff0c;投资于一个漂亮的网站是非常必要的。 经常看到…

用Python实现9大回归算法详解——01线形回归算法

1. 线性回归的基本概念 线性回归是一种最基本的监督学习算法&#xff0c;用于预测因变量&#xff08;目标变量&#xff09;和一个或多个自变量&#xff08;特征变量&#xff09;之间的关系。线性回归假设因变量与自变量之间的关系是线性的&#xff0c;即可以用以下形式的线性方…

2024国赛Word论文模板【一键生成式操作】

一、比赛介绍 该竞赛创办于1992年&#xff0c;每年一届&#xff0c;是首批列入“高校学科竞赛排行榜”的19项竞赛之一。2023年&#xff0c;来自全国及美国、澳大利亚、马来西亚的1685所院校/校区、59611队(本科54158队、专科5453队)、近18万人报名参赛。 而今年的国赛马上就要…

《Unity3D网络游戏实战》正确收发数据流

TCP数据流 系统缓冲区 当收到对端数据时&#xff0c;操作系统会将数据存入到Socket的接收缓冲区中 操作系统层面上的缓冲区完全由操作系统操作&#xff0c;程序并不能直接操作它们&#xff0c;只能通过socket.Receive、socket.Send等方法来间接操作。当系统的接收缓冲区为空&…

C#去掉文件夹或文件名非法字符

实现有输入字符串创建文件夹的功能&#xff0c;需要检查字符串中是否包含不能在文件夹中使用的非法字符 。C#中如果需要生成文件路径&#xff0c;有时会抛出“文件路径中出现非法字符”的异常&#xff0c;这时我们就会找到这个非法的字符串&#xff0c;然后Replace替换掉。net类…

牛客JS题(四十)字体高亮

注释很详细&#xff0c;直接上代码 涉及知识点&#xff1a; 正则表达式逆向思路 题干&#xff1a; 我的答案 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /></head><body><input type"text&…

图形编辑器基于Paper.js教程14:使用 Paper.js 绘制数学图形与交互的实现,画布缩放保持大小的圆,正弦,余弦,螺旋线

技术分析&#xff1a;使用 Paper.js 绘制数学图形与交互的实现 在现代Web开发中&#xff0c;动态图形和交互式视觉表现已成为提升用户体验的重要手段。通过一个详细的示例&#xff0c;我们将探索如何使用 Paper.js 进行数学图形&#xff08;正弦曲线、余弦曲线和螺旋线&#x…

拯救打工人的4款可ai生成ppt神器大PK,谁是加班狗的最爱?

在忙碌的工作日常里&#xff0c;做PPT常常让不少上班族头疼。晚上加班时&#xff0c;办公室里总能看到那些为了做出完美PPT而熬夜的人。不过现在好了&#xff0c;科技进步带来了好消息&#xff0c;有几款AI生成PPT的神器出现了&#xff0c;今天&#xff0c;咱们就来比一比&…

网络编程----TCP/IP协议

使用TCP/IP协议实现客户端和服务器端进行通信: 1.服务器端(test1.c): #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <stdio.h> #include <unistd.h>// 创建服务器端 int main() {//1.创建套接字int serfd…

锂电池剩余寿命预测 | Matlab基于Transformer-GRU的锂电池剩余寿命预测

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab基于Transformer-GRU的锂电池剩余寿命预测&#xff0c;Transformer结合门控循环单元。 Matlab基于Transformer-GRU的锂电池剩余寿命预测&#xff08;单变量&#xff09; 运行环境Matlab2023b及以上。 首先从…

API网关:SpringCloud GateWay

一. 网关的作用及背景 1.API网关的作用 请求路由 在我们的系统中由于同一个接口新老两套系统都在使用&#xff0c;我们需要根据请求上下文将请求路由到对应的接口。 统一鉴权 对于鉴权操作不涉及到业务逻辑&#xff0c;那么可以在网关层进行处理&#xff0c;不用下层到业务…

嵌入式开发--STM32的GPIO输入和输出复用

嵌入式开发–STM32的GPIO输入和输出复用 MCU的引脚数量非常有限&#xff0c;做项目时&#xff0c;经常是为了成本而选择引脚尽量少的芯片&#xff0c;这也给布线和编程带来更大的挑战。 最近一个项目&#xff0c;需要在某些时候通过拨码开关预置参数&#xff0c;预置完成后&am…

QT自定义系统快捷键任务

关键代码 //自定义快捷键检测 connect(this->ui->hotkeySequenceEdit_1, &QKeySequenceEdit::keySequenceChanged,this, &HotTestWidget::setShortcut_1);// 托盘显示 trayIcon new QSystemTrayIcon(this); QPixmap pixmap("tray.png"); QIcon icon(…

[Android] [解决]Bottom Navigation Views Activity工程带来的fragment顶部空白间距问题

用Android Stuio创建一个Bottom Navigation Views Activity工程&#xff0c; 我们刻意设置一下fragment背景为黑色&#xff0c;会发现&#xff0c;这个fragment离顶部还有一段不小空白距离&#xff0c; 怎么解决呢&#xff1f; 在activity_main.xml里面&#xff0c;删掉这句&a…