brpc之io事件分发器

结构

EventDispatcher
+int Start(const bthread_attr_t* consumer_thread_attr)
+int AddConsumer(SocketId socket_id, int fd)
+int RegisterEvent(SocketId socket_id, int fd, bool pollin)
+int UnregisterEvent(SocketId socket_id, int fd, bool pollin)
-static void* RunThis(void* arg)
-void Run()
-int RemoveConsumer(int fd)

初始化

brpc的io事件分发器,使用多线程Reactor模式
通过InitializeGlobalDispatchers来初始化全局io事件分发器
分为task_group_ntags组,每组有event_dispatcher_num

void InitializeGlobalDispatchers() {g_edisp = new EventDispatcher[FLAGS_task_group_ntags * FLAGS_event_dispatcher_num];for (int i = 0; i < FLAGS_task_group_ntags; ++i) {for (int j = 0; j < FLAGS_event_dispatcher_num; ++j) {bthread_attr_t attr =FLAGS_usercode_in_pthread ? BTHREAD_ATTR_PTHREAD : BTHREAD_ATTR_NORMAL;attr.tag = (BTHREAD_TAG_DEFAULT + i) % FLAGS_task_group_ntags;CHECK_EQ(0, g_edisp[i * FLAGS_event_dispatcher_num + j].Start(&attr));}}// This atexit is will be run before g_task_control.stop() because above// Start() initializes g_task_control by creating bthread (to run epoll/kqueue).CHECK_EQ(0, atexit(StopAndJoinGlobalDispatchers));
}

分发策略

EventDispatcher& GetGlobalEventDispatcher(int fd, bthread_tag_t tag) {pthread_once(&g_edisp_once, InitializeGlobalDispatchers);if (FLAGS_task_group_ntags == 1 && FLAGS_event_dispatcher_num == 1) {return g_edisp[0];}int index = butil::fmix32(fd) % FLAGS_event_dispatcher_num;return g_edisp[tag * FLAGS_event_dispatcher_num + index];
}

读事件

对于acceptor,读事件处理函数为OnNewConnections

options.on_edge_triggered_events = OnNewConnections;

连接后新socket的读事件处理函数为OnNewDataFromTcp或者OnNewMessages

#if BRPC_WITH_RDMAif (am->_use_rdma) {options.on_edge_triggered_events = rdma::RdmaEndpoint::OnNewDataFromTcp;} else {
#else{
#endifoptions.on_edge_triggered_events = InputMessenger::OnNewMessages;}

写事件

对于非阻塞connect时,会调用事件分发器的RegisterEvent注册EPOLLOUT

int Socket::Connect(const timespec* abstime,int (*on_connect)(int, int, void*), void* data) {if (_ssl_ctx) {_ssl_state = SSL_CONNECTING;} else {_ssl_state = SSL_OFF;}struct sockaddr_storage serv_addr;socklen_t addr_size = 0;if (butil::endpoint2sockaddr(remote_side(), &serv_addr, &addr_size) != 0) {PLOG(ERROR) << "Fail to get sockaddr";return -1;}butil::fd_guard sockfd(socket(serv_addr.ss_family, SOCK_STREAM, 0));if (sockfd < 0) {PLOG(ERROR) << "Fail to create socket";return -1;}CHECK_EQ(0, butil::make_close_on_exec(sockfd));// We need to do async connect (to manage the timeout by ourselves).CHECK_EQ(0, butil::make_non_blocking(sockfd));const int rc = ::connect(sockfd, (struct sockaddr*)&serv_addr, addr_size);if (rc != 0 && errno != EINPROGRESS) {PLOG(WARNING) << "Fail to connect to " << remote_side();return -1;}if (on_connect) {EpollOutRequest* req = new(std::nothrow) EpollOutRequest;if (req == NULL) {LOG(FATAL) << "Fail to new EpollOutRequest";return -1;}req->fd = sockfd;req->timer_id = 0;req->on_epollout_event = on_connect;req->data = data;// A temporary Socket to hold `EpollOutRequest', which will// be added into epoll device soonSocketId connect_id;SocketOptions options;options.bthread_tag = _bthread_tag;options.user = req;if (Socket::Create(options, &connect_id) != 0) {LOG(FATAL) << "Fail to create Socket";delete req;return -1;}// From now on, ownership of `req' has been transferred to// `connect_id'. We hold an additional reference here to// ensure `req' to be valid in this scopeSocketUniquePtr s;CHECK_EQ(0, Socket::Address(connect_id, &s));// Add `sockfd' into epoll so that `HandleEpollOutRequest' will// be called with `req' when epoll event reachesif (GetGlobalEventDispatcher(sockfd, _bthread_tag).RegisterEvent(connect_id, sockfd, false) !=0) {const int saved_errno = errno;PLOG(WARNING) << "Fail to add fd=" << sockfd << " into epoll";s->SetFailed(saved_errno, "Fail to add fd=%d into epoll: %s",(int)sockfd, berror(saved_errno));return -1;}// Register a timer for EpollOutRequest. Note that the timeout// callback has no race with the one above as both of them try// to `SetFailed' `connect_id' while only one of them can succeed// It also work when `HandleEpollOutRequest' has already been// called before adding the timer since it will be removed// inside destructor of `EpollOutRequest' after leaving this scopeif (abstime) {int rc = bthread_timer_add(&req->timer_id, *abstime,HandleEpollOutTimeout,(void*)connect_id);if (rc) {LOG(ERROR) << "Fail to add timer: " << berror(rc);s->SetFailed(rc, "Fail to add timer: %s", berror(rc));return -1;}}} else {if (WaitEpollOut(sockfd, false, abstime) != 0) {PLOG(WARNING) << "Fail to wait EPOLLOUT of fd=" << sockfd;return -1;}if (CheckConnected(sockfd) != 0) {return -1;}}return sockfd.release();
}

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

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

相关文章

GroupMamba: Parameter-Efficient and Accurate Group Visual State Space Model

GroupMamba: Parameter-Efficient and Accurate Group Visual State Space Model 1.介绍2.相关工作3.方法3.1预备知识3.2整体架构3.3调制组Mamba层3.3.1视觉单一选择性扫描&#xff08;Visual Single Selective Scan&#xff0c;简称VSSS&#xff09;块3.3.2分组Mamba操作3.3.3…

Vue 计算属性(computed)的使用和优化

前言 Vue 的计算属性&#xff08;computed&#xff09;是 Vue.js 中非常重要的一个概念。它允许你在 Vue 组件中定义一些计算逻辑&#xff0c;这些逻辑会依赖于 Vue 的响应式数据&#xff0c;并且具有缓存机制&#xff0c;只有在依赖数据发生改变时才会重新计算&#xff0c;从…

蓝桥杯—STM32G431RBT6(ADC数模转换,从原理到应用)

一、什么是ADC&#xff1f; ADC&#xff08;Analog-to-Digital Converter&#xff09;即模数转换器。它是一种将模拟信号转换为数字信号的电子器件。在电子系统中&#xff0c;ADC 起着至关重要的作用&#xff0c;它能将连续变化的模拟量&#xff08;如电压、电流等&#xff09;…

ps学习。

有大量的图要扣&#xff0c;淘宝5-15块扣一个&#xff0c;尽管蛮便宜的&#xff0c;但是架不住量大啊&#xff0c;还是好好ps&#xff0c;也能省一大笔钱。 填充 在这里有个油漆桶&#xff0c;一开始也叫渐变色&#xff0c;堆放在一起了&#xff0c;我觉得这不是个好设计。。…

pycharm 使用 translation 插件通过openai进行翻译

pycharm 使用 translation 插件通过openai进行翻译 1. 安装插件2. 配置插件3. 翻译 1. 安装插件 2. 配置插件 3. 翻译 调用 openai 时使用的提示词如下&#xff1a; <|im_start|>system\nYou are a translation engine that can only translate text and cannot interpr…

Vue学习记录之七(组件之间传参)

一、父传子 1、父组件传递 父&#xff1a; App.vue&#xff0c; 通过使用组件 <导入的组件名 :属性名1“” :属性名2“”></导入的组件名>,传递给子组件 传递了一个t字符串类型是不需要v-bind&#xff0c;也就是不需要冒号&#xff0c;非字符串类型的必须加 v-bi…

CTC loss 博客转载

论文地址&#xff1a; https://www.cs.toronto.edu/~graves/icml_2006.pdf 为了对应这个图&#xff0c;我们假设一种符合的模型情况&#xff1a; 英文OCR&#xff0c;37个类别&#xff08;26个小写字母10个汉字空格&#xff09;&#xff0c;最大输出长度8个字符 模型预测结果…

PCL 计算点云的平均密度(方法一)

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#xff08;长期更新&#xff09; 一、概述 本文将介绍如何计算点云的…

如何避开学习和研究机器人方向无价值的知识节约时间

往昔 这是一篇十年前就想写&#xff0c;但是一直没有实力和勇气落笔的文字。 如今 简约 授之以鱼&#xff0c;不如授之以渔。 啰嗦 机器人方向如何简单判定这个知识是否有价值。 只谈一个方向&#xff0c;就是这个知识点是“死”还是“活”&#xff1f; 什么是“死”&am…

element-ui表格操作大全

一、基础表格展示 数据绑定&#xff1a; 在el-table元素中注入data对象数组&#xff0c;在el-table-column&#xff08;列&#xff09;中使用prop属性来对应对象中的键名&#xff0c;使用label属性定义列名 元素案例内容&#xff1a; <el-table border :data"userL…

举例说明:自然语言处理实战项目

自然语言处理&#xff08;Natural Language Processing, NLP&#xff09;是人工智能领域的一个重要分支&#xff0c;旨在使计算机能够理解、解释和生成人类语言。以下是一些NLP实战项目的示例&#xff1a; 1. 情感分析&#xff08;Sentiment Analysis&#xff09; 项目描述: …

【LLM学习之路】9月16日 第六天

【LLM学习之路】9月16日 第六天 损失函数 L1Loss 可以取平均也可以求和 参数解析 input &#xff08;N&#xff0c;*&#xff09; N是batchsize&#xff0c;星号代表可以是任意维度 不是输入的参数&#xff0c;只是描述数据 target 形状要同上 MSELoss平方差 CrossEntr…

(done) 声音信号处理基础知识(5) (Types of Audio Features for Machine Learning)

参考&#xff1a;https://www.youtube.com/watch?vZZ9u1vUtcIA 声学特征描述了声音&#xff0c;不同特征捕捉声音的不同方面性质 声学特征有助于我们构建智能声学系统 声学特征分类有&#xff1a; 1.抽象等级 2.时域视野 3.音乐的部分 4.信号域 5.机器学习方法 如下图展示…

力扣中等 33.搜索旋转排序数组

文章目录 题目介绍题解 题目介绍 题解 首先用 153. 寻找旋转排序数组中的最小值 的方法&#xff0c;找到 nums 的最小值的下标 i。 然后分类讨论&#xff1a; 如果 target>nums[n−1]&#xff0c;在 [0,i−1] 中二分查找 target。 如果 target≤nums[n−1]&#xff0c;那…

51单片机——独立按键

一、独立按键对应单片机P3管脚&#xff0c;如图 二、按键点亮LED灯 #include <STC89C5xRC.H> void main() { while(1) { if(P300) { P200; } else { P201; } } } 当按键为0时&#xff0c;代表按下&#xff0c;所以当P30按下时&#xff0c;让P20&#xff1d;0&#…

二叉树(二)深度遍历和广度遍历

一、层序遍历 广度优先搜索&#xff1a;使用队列&#xff0c;先进先出 模板&#xff1a; 1、定义返回的result和用于辅助的队列 2、队列初始化&#xff1a; root非空时进队 3、遍历整个队列&#xff1a;大循环while(!que.empty()) 记录每层的size以及装每层结果的变量&a…

leetcode第十三题:罗马数字转整数

罗马数字包含以下七种字符: I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如&#x…

LeetCode[中等] 215. 数组中的第 K 个最大元素

给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 思路&#xff1a;基于快排改进的快速…

【全网最全】2024华为杯数学建模C题高质量成品查看论文!【附带全套代码+数据】

题 目&#xff1a; ___基于数据驱动下磁性元件的磁芯损耗建模 完整版获取&#xff1a; 点击链接加入群聊【2024华为杯数学建模助攻资料】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kxtS4vwn3gcv8oCYYyrqd0BvFc7tNfhV7&authKeyedQFZne%2BzvEfLEVg2v8FOm%…

计算机基础(Computer Fundamentals)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…