首页 > 其他分享 >spdy_buffer

spdy_buffer

时间:2023-05-23 16:31:48浏览次数:36  
标签:spdy buffer len int add 内存 offset


spdy_binary_buffer: 工具类,作用就是一个可以自动扩容和内存空间回收的buffer(主要用来保存http和spdy传输的内容),单位为字节(类型为unsigned char, 因为字符集的值都是>=0的)
<1> 几个关键的属性:
(1) unsigned char *buffer: 指向保存内容的那部分内存的开头。
(2) size_t len: len表示当前buffer的第一个可写的内存位置(buffer+len, 不代表buffer实际内容的长度,因为可能前面已经有内容被读出), 也是当前buffer实际内容的结尾的下一个位置。
(3) size_t allocated: 代表为此buffer分配的内存的长度。
(4) size_t offset: 代表当前buffer第一个可读的位置,也是当前buffer实际内容的开始内存位置(buffer+offset)。
(5) bool malloced: 代表此buffer使用的内存是否是专门为其malloc的(buffer使用的内存空间有很多来源,不一定就是自己malloc的)。

<2> buffer 内部提供了读取数据填充自己的工具(回调)函数接口,
通过将此函数的指针(read_callback) 以及 要读取的数据的来源(data) 传入read_from()函数来进行填充:

int binary_buffer::read_from(ReadCallback read_callback, void* data) 

 { 

 ................................... 

     added = read_callback(data, buffer+len, allocated-len); 

 ................................... 

 }



<3> 4种构造器:
(1) binary_buffer():
为自己malloc一块内存(buffer随后指向),len 和 offset均初始为0,allocated设为malloc内存的长度,malloced为true。
(2) binary_buffer(usigned char *data, int l):
malloced为false,buffer指向data, offset为0, 而len则为l(因为l代表已经写入buffer所指内存的内容的长度)。
(3) binary_buffer(const std::string &str):
同上,buffer指向的是str的c_str()产生的字符数组(强转为usigned char*)。
(4) binary_buffer(const binary_buffer &str):
同上,buffer直接指向了str这个buffer所使用的内存。

<4> 析构器:
如果内存是malloced的,那么就free。

<5> 一个真正的申请内存并拷贝内容的函数, 同时会将当前buffer的状态初始化,可以理解为一种变相构造器:
void set(const char *x, int l)
首先将len和offset重置为0,
然后如果之前没有自己的专属内存的话,就申请一块长度为l的内存,并将buffer指向其,更新allocated为l。
然后调用add函数将内容从x所指内存位置copy到自己的内存中.

<6> 关键的空间管理函数:
void add_space(int plen)
此函数的作用就是找到可用的长度为plen的内存空间:
(1)判断: offset == len && offset > 0, 这代表当前buffer的内容已经全部被读出,但是offset和len还没有被重置,
那么就进行重置。
(2)判断 plen + len <= allocated, 这代表从当前的第一个可写位置到内存的末尾的空间可以容下plen,直接返回.
(3)如果offset > 0并且 offset > len>>1(代表当前已经读取超过了写入内容的一半), 或者 len + plen - offset <= allocated
(整个内存所剩余的空间可以容下plen,和之前的len后面容下plen不同,这里还包括了offset前面因为读取而腾出的空间)
那么就可以将内存当前的整个内容部分迁移到内存的开头(buffer)来尝试腾出plen的连续内存空间(其实就是内存碎片整理),
offset重置为0(因为第一个可读的内存位置就是 buffer + 0), 而len -= offset(因为整个内容数组都向前平移了offset)
(4)如果plen还是不能被满足,那么就只能申请一块更大的内存了, 内存容量每次的增长固定的幅度,直到找一个能满足当前需求的容量,
然后realloc当前的内存, 更新buffer和allocated。

<7> void add( const unsigned char *p, size_t plen )
基础写入函数
从p所指的位置copy plen长度内容位置。
因为buffer容量有限,因此要先调add_space()来判断是否有足够内存以及不够的话整理扩容.
然后就直接memcpy

<8>int read( char *ptr, int num )
基础读取函数
力所能及的读取 长度为num的内容,但是如果buffer中剩余的内容不够num长,那么返回真正读取的长度,并memcpy相应长度内容到ptr。

<9>add类函数:

bool add( const std::string &x ); 将string的内容读入 

 bool add( const binary_buffer &x ); 将另外一个buffer的内容读入 

 bool add_int( int i, int bytes );将一个长度为bytes个byte长度的数(i)按byte为单位写入 

 bool add_byte( int i ); 读入一个byte 

 bool add_int16( int i ); 读入两个byte 

 bool add_int24( int i ) { return add_int(i,3); } 

 bool add_int32( int i );读入4个byte 

 bool add_hstring( const std::string &x, int bytes=2 ); 

 hstring是比较特殊的类型,在写入之前,要将其长度写入, bytes=2值得是存储长度这个值会占两个字节内存。 

 bool add_hstring( const char *x, int bytes=2 ); 

 binary_buffer *read_buffer( int bytes );


重新构造(new)一个buffer, 其buffer指向当前buffer的第一个读取位置,新buffer的内容长度是bytes

<10>重要的read函数:
int read_number( int bytes )
指明从buffer读取bytes个byte, 并且将其按位从高到低组合为一个unsigned int返回.

<11>控制函数:
void unread( int nbytes ) { assert( offset >= (unsigned)nbytes ); offset -= nbytes; }
将已经读取的nbytes个字符重新标为没有读取,即第一个读取位置回退nbytes(有边界判断)
void consume( int nbytes ){ offset += nbytes; assert(offset<=len); }
直接将nbytes个字符标记为已读,即第一个读取位置前进nbytes(边界判断)
void clear() { len = offset = 0; }
不释放内存,单纯丢弃以前的内容。
void filled( size_t bytes ) { len += bytes; assert(malloced && len <= allocated); }
直接写入bytes个 假 数据,使得可写位置前进bytes

<12>工具函数:
size_t length() const { return len-offset; }
size_t size() const { return len-offset; }
都返回实际内容的长度
const unsigned char *data() const { return buffer+offset; }
返回第一个可读位置的内存地址
unsigned char *write_pointer( size_t nbytes );
返回第一个可写位置的内存地址,同时还要求有nbytes长度的可写内存。

标签:spdy,buffer,len,int,add,内存,offset
From: https://blog.51cto.com/u_9420214/6333355

相关文章

  • 深入解析buffer busy waits
    在写一个培训ppt的时候,为了深入理解buffebusywaits这个等待事件,做了一个仔细的测试,对大家也有帮助,经过测试,发现我个人以前的认识都有一点问题。大家一起探讨!1.创建测试表www.killdb.com>connroger/rogerConnected.www.killdb.com>create......
  • 现代计算机图形学——P6. Rasterization 2(Antialiasing and Z-Buffering)(光栅化(反走样
      ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————......
  • HTB ACADEMY-Stack-Based Buffer Overflows on Linux x86 WRITE UP
    WewereabletogainSSHaccesstoaLinuxmachinewhosepasswordwasreusedbyanothermachineduringourpenetrationtest.Onthismachine,wehaveastandarduser"htb-student"whocanleaveamessagetotheadministratorusingaself-written......
  • python 项目报错 Fatal Python error: _enter_buffered_busy: could not acquire lock
    FatalPythonerror:_enter_buffered_busy:couldnotacquirelockfor<_io.BufferedWritername=''>atinterpretershutdown,possiblyduetodaemonthreadsPythonruntimestate:finalizing(tstate=0x00005654c4008a40)Currentthread0x00007fc......
  • KingbaseES V8R6 等待事件之LWLock Buffer_IO
    等待事件含义当进程同时尝试访问相同页面时,等待其他进程完成其输入/输出(I/O)操作时,会发生LWLock:BufferIO等待事件。其目的是将同一页读取到共享缓冲区中。每个共享缓冲区都有一个与LWLock:BufferIO等待事件相关联的I/O锁,每次都必须在共享缓冲区外部检索页。此锁用于处理多个会......
  • Linux中Buffer和Cache的区别
    Linux中Buffer和Cache的区别1.cache,缓存区,是高速缓存。是位于CPU和主内存之间的容量较小但速度很快的存储器,因为CPU的速度远远高于主内存的速度,CPU从内存中读取数据需等待很长的时间,而 Cache保存着CPU刚用过的数据或循环使用的部分数据,这时从Cache中读取数据会更快,减少了CPU......
  • Go源码阅读——github.com/medcl/esm —— buffer.go
    esm(AnElasticsearchMigrationTool)—— buffer.gohttps://github.com/medcl/esmrelease:8.7.1通过阅读好的源代码,细致思考,理性分析并借鉴优秀实践经验,提高zuoyang的编程水平,所谓"他山之石,可以攻玉" 该是如此吧。 /*CopyrightMedcl(mATmedcl.net)Licensedun......
  • MySQL双写缓冲区(Doublewrite Buffer)
    本文已收录至Github,推荐阅读......
  • (转)Java中的String、StringBuilder和StringBuffer
    1、StringString对象是不可变的,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。那么我们new一个String对象,比如Stringa=newString("A")Stringa2=newString("A")和直接创建一个字符串,比如Stringb="A"这两种方......
  • 浅谈Protocol Buffers、GRPC、Buf、GRPC-Gateway
    1.ProtocolBuffers什么是proto?ProtocolBuffers如何理解ProtocolBuffers?协议缓冲区非proto协议如何订立、传播以及维护?如何理解协议缓冲区?Protocolbuffers提供了一种语言中立、平台中立、可扩展的机制,用于以向前兼容和向后兼容的方式序列化结构化数据。它......