libevent源码学习5---数据封装evBuffer

libevent源码学习5—数据封装evBuffer

libevent 的 evbuffer 实现了为向后面添加数据和从前面移除数据而优化的字节队列。

evbuffer 用于处理缓冲网络 IO 的“缓冲”部分。它不提供调度 IO 或者当 IO 就绪时触发 IO 的 功能,这是 bufferevent 的工作。

struct bufferevent;
struct evbuffer_chain;
struct evbuffer {/** The first chain in this buffer's linked list of chains. */struct evbuffer_chain *first;/** The last chain in this buffer's linked list of chains. */struct evbuffer_chain *last;/** Pointer to the next pointer pointing at the 'last_with_data' chain.** To unpack:** The last_with_data chain is the last chain that has any data in it.* If all chains in the buffer are empty, it is the first chain.* If the buffer has no chains, it is NULL.** The last_with_datap pointer points at _whatever 'next' pointer_* pointing at the last_with_data chain. If the last_with_data chain* is the first chain, or it is NULL, then the last_with_datap pointer* is &buf->first.*/struct evbuffer_chain **last_with_datap;/** Total amount of bytes stored in all chains.*/size_t total_len;/** Number of bytes we have added to the buffer since we last tried to* invoke callbacks. */size_t n_add_for_cb;/** Number of bytes we have removed from the buffer since we last* tried to invoke callbacks. */size_t n_del_for_cb;#ifndef EVENT__DISABLE_THREAD_SUPPORT/** A lock used to mediate access to this buffer. */void *lock;
#endif/** True iff we should free the lock field when we free this* evbuffer. */unsigned own_lock : 1;/** True iff we should not allow changes to the front of the buffer* (drains or prepends). */unsigned freeze_start : 1;/** True iff we should not allow changes to the end of the buffer* (appends) */unsigned freeze_end : 1;/** True iff this evbuffer's callbacks are not invoked immediately* upon a change in the buffer, but instead are deferred to be invoked* from the event_base's loop.	Useful for preventing enormous stack* overflows when we have mutually recursive callbacks, and for* serializing callbacks in a single thread. */unsigned deferred_cbs : 1;
#ifdef _WIN32/** True iff this buffer is set up for overlapped IO. */unsigned is_overlapped : 1;
#endif/** Zero or more EVBUFFER_FLAG_* bits */ev_uint32_t flags;/** Used to implement deferred callbacks. */struct event_base *cb_queue;/** A reference count on this evbuffer.	 When the reference count* reaches 0, the buffer is destroyed.	Manipulated with* evbuffer_incref and evbuffer_decref_and_unlock and* evbuffer_free. */int refcnt;/** A struct event_callback handle to make all of this buffer's callbacks* invoked from the event loop. */struct event_callback deferred;/** A doubly-linked-list of callback functions */LIST_HEAD(evbuffer_cb_queue, evbuffer_cb_entry) callbacks;/** The parent bufferevent object this evbuffer belongs to.* NULL if the evbuffer stands alone. */struct bufferevent *parent;
};

5.1 创建和释放evbuffer

struct evbuffer *evbuffer_new(void);
void evbuffer_free(struct evbuffer *buf);

实现也很简洁,不解释了

struct evbuffer *evbuffer_new(void)
{struct evbuffer *buffer;buffer = mm_calloc(1, sizeof(struct evbuffer));if (buffer == NULL)return (NULL);LIST_INIT(&buffer->callbacks);buffer->refcnt = 1;buffer->last_with_datap = &buffer->first;return (buffer);
}
void evbuffer_free(struct evbuffer *buffer)
{EVBUFFER_LOCK(buffer);evbuffer_decref_and_unlock_(buffer);
}void evbuffer_decref_and_unlock_(struct evbuffer *buffer)
{struct evbuffer_chain *chain, *next;ASSERT_EVBUFFER_LOCKED(buffer);EVUTIL_ASSERT(buffer->refcnt > 0);if (--buffer->refcnt > 0) {EVBUFFER_UNLOCK(buffer);return;}for (chain = buffer->first; chain != NULL; chain = next) {next = chain->next;evbuffer_chain_free(chain);}evbuffer_remove_all_callbacks(buffer);if (buffer->deferred_cbs)event_deferred_cb_cancel_(buffer->cb_queue, &buffer->deferred);EVBUFFER_UNLOCK(buffer);if (buffer->own_lock)EVTHREAD_FREE_LOCK(buffer->lock, EVTHREAD_LOCKTYPE_RECURSIVE);mm_free(buffer);
}

5.2 evbuffer与线程安全

int evbuffer_enable_locking(struct evbuffer *buf, void *lock);
void evbuffer_lock(struct evbuffer *buf);
void evbuffer_unlock(struct evbuffer *buf);

默认情况下,在多个线程中同时访问 evbuffer 是不安全的。如果需要这样的访问,可以调用 evbuffer_enable_locking() 以启用对evbuffer的锁定 。

// 参数
@param buf An evbuffer to make lockable.
@param lock A lock object, or NULL if we should allocate our own.
@return 0 on success, -1 on failure.// 实现
int evbuffer_enable_locking(struct evbuffer *buf, void *lock)
{
#ifdef EVENT__DISABLE_THREAD_SUPPORTreturn -1;
#elseif (buf->lock)return -1;if (!lock) {EVTHREAD_ALLOC_LOCK(lock, EVTHREAD_LOCKTYPE_RECURSIVE);if (!lock)return -1;buf->lock = lock;buf->own_lock = 1;} else {buf->lock = lock;buf->own_lock = 0;}return 0;
#endif
}

evbuffer_lock()evbuffer_unlock()函数分别请求和释放 evbuffer 上的锁。可以使用这两个函数让一系列操作是原子的。如果 evbuffer 没有启用锁,这两个函数不做任何操作。

5.3 检查evbuffer

/**Returns the total number of bytes stored in the evbuffer@param buf pointer to the evbuffer@return the number of bytes stored in the evbuffer
*/
size_t evbuffer_get_length(const struct evbuffer *buf);

5.4 向evbuffer添加数据

/**Append data to the end of an evbuffer.@param buf the evbuffer to be appended to@param data pointer to the beginning of the data buffer@param datlen the number of bytes to be copied from the data buffer@return 0 on success, -1 on failure.*/
int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen);
/**Append a formatted string to the end of an evbuffer.The string is formated as printf.@param buf the evbuffer that will be appended to@param fmt a format string@param ... arguments that will be passed to printf(3)@return The number of bytes added if successful, or -1 if an error occurred.@see evutil_printf(), evbuffer_add_vprintf()*/
int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
/**Expands the available space in an evbuffer.Expands the available space in the evbuffer to at least datlen, so thatappending datlen additional bytes will not require any new allocations.@param buf the evbuffer to be expanded@param datlen the new minimum length requirement@return 0 if successful, or -1 if an error occurred
*/
int evbuffer_expand(struct evbuffer *buf, size_t datlen);

5.5 evbuffer数据移动

为提高效率,libevent 具有将数据从一个 evbuffer 移动到另一个的优化函数。

/**Move all data from one evbuffer into another evbuffer.This is a destructive add.  The data from one buffer moves intothe other buffer.  However, no unnecessary memory copies occur.@param outbuf the output buffer@param inbuf the input buffer@return 0 if successful, or -1 if an error occurred@see evbuffer_remove_buffer()*/
EVENT2_EXPORT_SYMBOL
int evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf);
/**Read data from an evbuffer into another evbuffer, drainingthe bytes from the source buffer.  This function avoids copyoperations to the extent possible.If more bytes are requested than are available in src, the srcbuffer is drained completely.@param src the evbuffer to be read from@param dst the destination evbuffer to store the result into@param datlen the maximum numbers of bytes to transfer@return the number of bytes read*/
EVENT2_EXPORT_SYMBOL
int evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,size_t datlen);

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

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

相关文章

ChatGPT在高等教育中的应用利弊探讨

​人工智能在教育领域的应用日益广泛。2022年11月OpenAI开发的聊天机器人ChatGPT在全球范围内流传开来,其中用户数量最多的国家是美国(15.22%)。由于ChatGPT应用广泛,具有类似人类回答问题的能力,它正在成为许多学生和教育工作者的可信赖伙伴…

【图像分割】实现snake模型的活动轮廓模型以进行图像分割研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

企业网络日志安全与 EventLog Analyzer

企业的网络日志安全是一项至关重要的任务。随着信息技术的迅猛发展,网络攻击和数据泄露的威胁也与日俱增。为了应对这些威胁,企业需要强大的工具来监控、分析和保护其网络日志。而ManageEngine的EventLog Analyzer正是这样一款卓越的解决方案。 网络日志…

前端面试:【浏览器与渲染引擎】Web APIs - DOM、XHR、Fetch、Canvas

嗨,亲爱的读者!当我们在浏览器中浏览网页时,我们常常会与各种Web API打交道。这些API允许我们与网页内容、服务器资源和图形进行交互。本文将深入探讨一些常见的Web API,包括DOM、XHR、Fetch和Canvas,以帮助你了解它们…

java Spring Boot将不同配置拆分入不同文件管理

关于java多环境开发 最后还有一个小点 我们一般会将不同的配置 放在不同的配置文件中 好处肯定就在于 想换的时候非常方便 那么 我们直接看代码 我们将项目中的 application.yml 更改代码如下 spring:profiles:active: dev这里 意思是 我们选择了dev 环境 然后创建一个文件 …

C++ 工具

C参考手册 Learncppcplusplustutorialspoint/cplusplusAwesomeC 写在最后:若本文对您有帮助,请点个赞啦 ٩(๑•̀ω•́๑)۶

Go 自学:Array阵列

以下代码展示了用两种方法建立array。 package mainimport "fmt"func main() {var fruitList [4]stringfruitList[0] "Apple"fruitList[1] "Tomato"fruitList[3] "Peach"fmt.Println("Fruit list is: ", fruitList)fmt.…

Spring Cloud 微服务

0.学习目标 了解系统架构的演变了解RPC与Http的区别掌握HttpClient的简单使用知道什么是SpringCloud独立搭建Eureka注册中心独立配置Robbin负载均衡 -Xms128m -Xmx128m 1.系统架构演变 随着互联网的发展,网站应用的规模不断扩大。需求的激增,带来的是…

【C++】C++ 引用详解 ⑦ ( 指针的引用 )

文章目录 一、二级指针可实现的效果二、指针的引用1、指针的引用 等同于 二级指针 ( 重点概念 )2、引用本质 - 函数间接赋值简化版本3、代码示例 - 指针的引用 一、二级指针可实现的效果 指针的引用 效果 等同于 二级指针 , 因此这里先介绍 二级指针 ; 使用 二级指针 作为参数 …

字节实习后端面试总结(C++/GO)

语言 C ++, Python 哪一个更快? 答:这个我不知道从哪方面说,就是 C + + 的话,它其实能够提供开发者非常多的权限,就是说它能涉及到一些操作系统级别的一些操作,速度应该挺快。然后 Python 实现功能还是蛮快的。 补充: 一般而言,C++更快一些,因为它是一种编译型语…

C++对象模型和this指针

1 成员变量和成员函数分开存储 在C中,类内的成员变量和成员函数分开存储 只有非静态成员变量才属于类的对象上 class Person { public:Person() {mA 0;}//非静态成员变量占对象空间int mA;//静态成员变量不占对象空间static int mB; //函数也不占对象空间&#…

基于CNN卷积神经网络的目标识别matlab仿真,数据库采用cifar-10

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ....................................................................... %定义网络层 lay…

【vue3+elementplus】文件上传

二次封装的el-upload <template><div class"uploadFile"><el-uploadref"upload":action"props.action":accept"props.accept":on-progress"handleProgress":on-preview"handlePreview":on-succes…

代码随想录算法训练营第四十六天|139.单词拆分、多重背包、背包问题总结

139.单词拆分 ★ 文档讲解 &#xff1a; 代码随想录 - 139.单词拆分 状态&#xff1a;再次回顾。&#xff08;★&#xff1a;需要多次回顾并重点回顾&#xff09; 本题其实不套完全背包思路来理解反而更简单易懂一点。 动态规划五部曲&#xff1a; 确定dp数组&#xff08;dp ta…

相机成像之3A算法的综述

3A算法是摄像机成像控制技术中的三大自动控制算法。随着计算机视觉的迅速发展,该算法在摄像器材领域具有广泛的应用和前景。 那么3A控制算法又是指什么呢? (1)AE (Auto Exposure)自动曝光控制 (2)AF (Auto Focus)自动聚焦控制 (3)AWB (Auto White Balance)自动白平衡控…

Android面试题:MVC、MVP、MVVM

MVC模式&#xff1a; MVC结构&#xff1a; 1.MVC(Model-View-Controller) 2.Model:对数据库的操作、对网络等的操作都应该在Model里面处理&#xff0c;当然对业务计算&#xff0c;变更等操作也是必须放在的该层的。 3.View:主要包括一下View及ViewGroup控件&#xff0c;可以是…

RHCE——八、DNS域名解析服务器

RHCE 一、概述1、产生原因2、作用3、连接方式4、因特网的域名结构4.1 拓扑4.2 分类4.3 域名服务器类型划分 二、DNS域名解析过程1、分类2、解析图&#xff1a;2.1 图&#xff1a;2.2 过程分析 三、搭建DNS域名解析服务器1、概述2、安装软件3、/bind服务中三个关键文件4、配置文…

Arduino驱动TEMT6000传感器(光照传感器篇)

目录 1、传感器特性 2、硬件原理图 3、驱动程序 TEMT6000是一个三极管类型的光敏传感器,其光照强度和基极的电流成正比。用起来也相当简单,可以简单的连接该传感器的基极到模拟电压输入,通过简单的检测电压值就可以判断当前的光照强度。 1、

Vue.js知识点学习的一点笔记

一、虚拟DOM 1、原生JS是命令式编程&#xff0c;当渲染在页面的数据发生一点点变化&#xff0c;需要整个重新渲染一编。vue.js渐进式框架有个虚拟DOM的概念&#xff0c;运用diff算法&#xff0c;比较新旧数据&#xff0c;相同的数据不变不重渲染&#xff0c;不同的部分新数据…

使用Navicat连接数据库报错-解决方式

报错&#xff1a; 1045-Access denied for user rootlocalhost(using passwordYES) 1. win r 打开&#xff1a; powerShell 2. 启动&#xff1a; net start mysql 3. 重置&#xff1a; mysql -u root -p 4.修改密码&#xff1a; mysql8.0前的版本修改密码的命令&…