【sylar-webserver】5 协程调度模块

文章目录

  • 设计思路
    • 三种协程的切换

协程调度模块,需要把前面的线程模块和协程模块结合使用 ~

设计思路

  • 构造函数定义 线程池 基本信息。
  • start(),创建线程池,每个线程创建都执行 run()。
  • 每个线程在 run() 里,查找任务队列 m_tasks。如果获取到任务后,创建协程并切换执行 ~ 如果没任务切换到 idel 协程等待 ~
  • 添加任务到 m_tasks。
  • stop(),调用tickle(),唤醒所有线程,等待所有的任务完成。

主要的函数:

  1. 构造函数
  2. Scheduler(size_t threads, bool use_caller, const std::string &name) // 模板函数,添加任务
  3. start()
  4. run()
  5. stop()

主要的变量:

  • 线程变量:
    • static thread_local Scheduler* t_scheduler;当前线程的调度器,同一个调度器下的所有线程贡献同一个实例。
    • static thread_local Fiber* t_scheduler_fiber; 当前线程的调度协程,每个线程都独一份。
  • Scheduler类变量
    • std::vector<Thread::ptr> m_threads; 线程池
    • std::list<ScheduleTask> m_tasks; 任务队列
    • bool m_useCaller; 主线程是否添加调度
      • 当 m_useCaller = true; 主线程添加调度
      • Fiber::ptr m_rootFiber; 调度器所在线程的调度协程
      • int m_rootThread; 调度所在的线程id

具体调度需要细分情况:

  • 主线程不添加到调度器
    这种较为简单。

    • Scheduler(),定义线程池变量
    • start(),创建子线程 执行 run()
    • run(),如果是子线程,需要创建主协程赋值给 t_scheduler_fiber 作为调度协程。idle_fiber协程。cb_fiber任务协程。从任务队列拿去任务,然后设置cb_fiber,切换执行。(主协程 <----> cb_fiber)。如果没有任务,切换idel协程,阻塞(iomanager里会使用epoll_wait重写这个方法,这里还只是象征性的 等待。重写需要注意,idle_fiber是在while循环里,也就是只要不stop,idle_fiber会一直存在。)(主协程 <----> idle_fiber)。
    • stop(),设置m_stopping,唤起子线程,等待任务执行结束。【纯线程池 模型下,只要是外部线程即可stop】
  • 主线程添加到调度器
    其实这里,最重要的是 三协程的切换设置。
    (主协程 — 调度协程 — 任务协程)

    • Scheduler(),定义线程池变量。创建调度协程赋值 m_rootFiber 作为当前主线程的调度协程,运行run()。赋值t_scheduler_fiber = m_rootFiber.get() ,这就是当前主线程的调度协程。赋值 m_rootThread 当前主线程(用于判断是否是主线程)。
    • start(),同上,创建子线程,执行run()
    • run(),此时额外增加 主线程的 调度过程。如果是主线程,那么 t_scheduler_fiber 已经赋值为调度协程。直接拿去任务执行,或者切换idle等待。
    • stop(),特殊性在于,主线程一直是主协程在 初始化/添加任务。只有在stop里,切换到 m_rootFiber 调度协程消费任务。【use_caller 模式下执行stop(),必须是主线程,因为我们需要 切换到 主线程里的调度协程 消费一下任务】

三种协程的切换

对于 主协程,调度协程,任务协程。

重构了 协程模块 里的 yield 和 resume
yield:任务协程 --> 调度协程 —> 主协程
resume: 主协程 —> 调度协程 —> 任务协程

Fiber增加一个类变量
bool m_runInScheduler; // 本协程是否参与调度器调度,相当于当前协程是否是任务协程。

void Fiber::yield(){SYLAR_ASSERT(m_state == TERM || m_state == RUNNING)     // 当前子协程可以是 TERM,RUNNINGif(m_state != TERM){    // 如果没有结束,中途进行yield,状态设置为READY,可能还会回来继续执行。m_state = READY;}if(m_runInScheduler){if(swapcontext(&m_ctx, &(Scheduler::GetMainFiber()->m_ctx))){...}}else{if(swapcontext(&m_ctx, &(t_thread_fiber->m_ctx))){...}}
}void Fiber::resume(){SYLAR_ASSERT(m_state == READY);// 切换前,提前设置状态和 当前线程运行的协程。SetThis(this);m_state = RUNNING;if(m_runInScheduler){ // 相当于当前协程,是任务协程。 t_scheduler_fiber --> t_fiberif(swapcontext(&(Scheduler::GetMainFiber()->m_ctx), &m_ctx)){...}}else { // t_thread_fiber --> t_scheduler_fiberif(swapcontext(&(t_thread_fiber->m_ctx), &m_ctx)){...}}
}

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

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

相关文章

Go 语言规范学习(1)

文章目录 IntroductionNotation示例&#xff08;Go 语言的 if 语句&#xff09;&#xff1a; Source code representationCharacters例子&#xff1a;变量名可以是中文 Letters and digits Lexical elementsCommentsTokensSemicolons例子&#xff1a;查看程序所有的token Ident…

探索抓包利器ProxyPin,实现手机APP请求抓包,支持https请求

以下是ProxyPin的简单介绍&#xff1a; - ProxyPin是一个开源免费HTTP(S)流量捕获神器&#xff0c;支持 Windows、Mac、Android、IOS、Linux 全平台系统- 可以使用它来拦截、检查并重写HTTP(S)流量&#xff0c;支持捕获各种应用的网络请求。ProxyPin基于Flutter开发&#xff0…

深度学习3-pytorch学习

深度学习3-pytorch学习 Tensor 定义与 PyTorch 操作 1. Tensor 定义&#xff1a; Tensor 是 PyTorch 中的数据结构&#xff0c;类似于 NumPy 数组。可以通过不同方式创建 tensor 对象&#xff1a; import torch# 定义一个 1D Tensor x1 torch.Tensor([3, 4])# 定义一个 Fl…

深入浅出Spring-Boot-3.x.pdf

通过网盘分享的文件&#xff1a;深入浅出Spring-Boot-3.x.pdf 链接: https://pan.baidu.com/s/10ZkhmeIXphEwND9Rv4EBlg?pwduatm 提取码: uatm

springboot启动事件CommandLineRunner使用

什么是CommandRunner CommandRunner是springboot启动完成时会调用的一个runner 启动参数会传递到这个runner 我们能用来做一些初始化工作和缓存预热等工作 ApplicationRunner VS CommandRunner? 这两个Runner作用一样 只是得到的启动参数格式不一样 前者是一个Argument对象…

数据可视化TensorboardX和tensorBoard安装及使用

tensorBoard 和TensorboardX 安装及使用指南 tensorBoard 和 TensorBoardX 是用于可视化机器学习实验和模型训练过程的工具。TensorBoard 是 TensorFlow 官方提供的可视化工具&#xff0c;而 TensorBoardX 是其社区驱动的替代品&#xff0c;支持 PyTorch 等其他框架。以下是它…

蓝桥杯C++基础算法-多重背包

这段代码实现了一个多重背包问题的动态规划解法。多重背包问题与完全背包问题类似&#xff0c;但每个物品有其数量限制。以下是代码的详细思路解析&#xff1a; 1. 问题背景 给定 n 个物品&#xff0c;每个物品有其体积 v[i]、价值 w[i] 和数量 s[i]&#xff0c;以及一个容量为…

【SUNO】【AI作词】【提示词】

仿写歌词提示词模板&#xff08;升级版&#xff09; 一、仿写目标 风格定位 音乐风格&#xff1a; [填写目标风格&#xff0c;如&#xff1a;民谣/流行/古风/电子/爵士等]参考案例&#xff1a;如《成都》的叙事民谣&#xff0c;《孤勇者》的励志流行。 情感基调&#xff1a; […

26考研——树与二叉树_树与二叉树的应用(5)

408答疑 文章目录 三、树与二叉树的应用哈夫曼树和哈夫曼编码哈夫曼树的定义概念带权路径长度&#xff08;WPL&#xff09;计算示例分析 哈夫曼树的构造算法描述哈夫曼树的性质示例 哈夫曼编码Huffman树的编码规则Huffman树的构建过程前缀编码前缀编码的分析及应用 Huffman树的…

【VUE】day06 动态组件 插槽 自定义指令 ESlint

【VUE】day06 动态组件 & 插槽 & 自定义指令 1. 动态组件1.1 通过不同的按钮展示不同的组件1.1.1回顾click 1.2 keep-alive的使用1.3 keep-alive对应的生命周期函数1.3.1 keep-alive的include属性1.3.2 exclude 1.4 组件注册名称和组件声明时name的区别1.4.1 组件声明时…

nodejs-原型污染链

还是老规矩&#xff0c;边写边学&#xff0c;先分享两篇文章 深入理解 JavaScript Prototype 污染攻击 | 离别歌 《JavaScript百炼成仙》 全书知识点整理-CSDN博客 Ctfshow web入门 nodejs篇 web334-web344_web334 ctfshow-CSDN博客 334-js审计 var express require(expr…

Oracle 数据库通过exp/imp工具迁移指定数据表

项目需求&#xff1a;从prod数据库迁移和复制2个表(BANK_STATE&#xff0c;HBS)的数据到uat数据库环境。 数据库版本&#xff1a;Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 迁移工具&#xff1a;客户端exp/imp工具 -- 执行命令 从Prod数据库导出数据exp us…

企业级基于SpringBoot的MQTT的构建和使用

基于SpringBoot的MQTT配置及使用 首先要使用EMQX搭建一个MQTT服务器&#xff0c;参考文档&#xff1a;EMQX快速开始 本着开源分享的观点&#xff0c;闲话不多说&#xff0c;直接上代码 导入Maven <dependency><groupId>org.springframework.integration</gro…

26考研——图_图的代码实操(6)

408答疑 文章目录 五、图的代码实操图的存储邻接矩阵结构定义初始化插入顶点获取顶点位置在顶点 v1 和 v2 之间插入边获取第一个邻接顶点获取下一个邻接顶点显示图 邻接表结构定义初始化图插入顶点获取顶点位置在顶点 v1 和 v2 之间插入边获取第一个邻接顶点获取下一个邻接顶点…

开源webmail邮箱客户端rainloop的分支版本SnappyMail 设置发件人允许多重身份

RainLoop已多年未更新&#xff0c;SnappyMail 是 RainLoop 的分支&#xff0c;由社区维护。SnappyMail 不仅修复了漏洞&#xff0c;还增加了更多功能和优化。对 IMAP 支持更好&#xff0c;移动端体验也比 RainLoop 更细致。 安装过程和设置跟RainLoop一样&#xff1a; 以宝塔面…

海量数据场景题--查找两个大文件的URL

查找两个大文件共同的URL 给定 a、b 两个文件&#xff0c;各存放 50 亿个 URL&#xff0c;每个 URL 各占 64B&#xff0c;找出 a、b 两个文件共同的 URL。内存限制是 4G。 操作逻辑&#xff1a; 使用哈希函数 hash(URL) % 1000​ 将每个URL映射到0-999的编号 文件A切割为a0, a1…

简单ELK框架搭建

简介 ELK 框架是一套开源的日志管理和分析工具&#xff0c;由 Elasticsearch、Logstash 和 Kibana 三个主要组件组成&#xff0c;现在新增了Filebeat组件&#xff0c;可以更高效的收集数据。 Elasticsearch&#xff1a;是一个分布式、高可扩展的开源搜索引擎&#xff0c;能快速…

VS Code 中 .history`文件的来源与 .gitignore`的正确使用

引言 在使用 VS Code 进行 Git 版本控制时&#xff0c;有时会发现项目中多出一个 .history 目录&#xff0c;并被 Git 识别为未跟踪文件。本文将解释 .history 的来源&#xff0c;并提供 .gitignore 的正确配置方法&#xff0c;确保开发环境的整洁性。 1. .history 文件的来源…

网络之数据链路层

数据链路层 数据链路层目标 TCP/IP提供了一种能力, 将数据可靠的从 B 跨网络送到 C 主机, 这期间是由无数次局域网转发构成的, 比如 主机B 到 路由器F 就是一次局域网通信的问题, 而数据链路层就是研究数据是如何在局域网内部转发的. 也就是说, 应用层是进行数据的处理, 传输…

A Brief History: from GPT-1 to GPT-3

This is my reading notes of 《Developing Apps with GPT-4 and ChatGPT》. In this section, we will introduce the evolution of the OpenAI GPT medels from GPT-1 to GPT-4. GPT-1 In mid-2018, OpenAI published a paper titled “Improving Language Understanding …