网站ui,58同城 网站建设,天津百度seo推广,做网站那个公司比较好重写Sylar基于协程的服务器#xff08;3、协程模块的设计#xff09;
重写Sylar基于协程的服务器系列#xff1a; 重写Sylar基于协程的服务器#xff08;0、搭建开发环境以及项目框架 || 下载编译简化版Sylar#xff09; 重写Sylar基于协程的服务器#xff08;1、日志模…重写Sylar基于协程的服务器3、协程模块的设计
重写Sylar基于协程的服务器系列 重写Sylar基于协程的服务器0、搭建开发环境以及项目框架 || 下载编译简化版Sylar 重写Sylar基于协程的服务器1、日志模块的架构
重写Sylar基于协程的服务器2、配置模块的设计
重写Sylar基于协程的服务器3、协程模块的设计
前言
关于线程以及线程并发的封装在此略过该部分比较简单有兴趣的朋友可以看一下我原来写的Muduo的博客muduo源码阅读笔记2、对C语言原生的线程安全以及同步的API的封装、muduo源码阅读笔记3、线程和线程池的封装或者直接阅读本文配套的简化版sylar的源码https://github.com/LunarStore/lunar。
协程模块的设计与实现
协程的状态定义
协程分为初始化状态、执行状态、阻塞状态、就绪状态、结束状态、异常状态。定义如下
enum State{INIT, // 初始化EXEC, // 执行HOLD, // 阻塞READY, // 就绪TERM, // 结束EXCE // 异常
};协程的状态机
任务协程
一个任务协程运行时可能的状态机图如下图: 可能跟着协程调度模块、io协程调度模块走一遍调度任务协程的流程后才能清晰的理解该图的意义这里可以先以整体的视角看一看一个任务协程的状态切换时机即可。笔者能力有限不足的地方可以在评论区指出。
调度协程Idle协程
正常情况下调度协程和Idle协程的状态机如下图 协程模块的设计如下
总体来讲协程模块Fiber类主要就是对ucontext_t提供的getcontext、makecontext、swapcontext等函数做了一个封装为了简化后续调度模块使用协程。要讲清楚协程模块不得不引入类型为Finer::ptr就是Fiber对象的智能指针三个重要的线程全局变量分别是线程原始协程t_threadFiber、线程当前正在运行的协程t_fiber、调度协程t_scheRunFiber这三个全局变量在每个线程中都会拥有一份独立于其他线程。由于引入了协程的概念我们就应该弱化线程的概念以一切皆是协程的思想去编写代码。所以一个线程在被创建时它原始的上下文就可以作为一个协程我们把它的上下文保存在t_threadFiber中这样可以待线程的其他协程执行完毕再切换回来。具体类的设计如下 构造函数用户在构造一个协程时会传入协程的回调函数、协程堆栈大小、指明协程在切入去执行时是和哪个协程做切换t_threadFiber或者t_scheRunFiber这里额外再解释一下因为一个协程的切入可以看成是在另一个协程中进行的所以一个协程在切入执行前首先要保存先前协程的上下文因为我们实现的协程服务器是有调度器的而且每个线程会执行调度协程进行任务协程的调度所以一般任务协程在切入执行前是要先将上下文保存在t_scheRunFiber中再将上下文修改成任务协程的上下文。待任务协程执行完毕或者阻塞再反向操作先将上下文保存到任务协程中再将上下文还原成t_scheRunFiber去调度其他协程。 协程初始化首先会调用getcontext初始化m_ctx成员变量该成员变量是保存协程的上下文核心数据结构然后调用makecontext将协程上下文设置成静态成员函数MainFun在静态成员函数MainFun中会通过线程局部变量t_fiber切入时设置获取到协程当前运行的协程对象进而回调用户传来的call back函数。 协程默认构造该构造是私有化的专门为线程原始的协程打造内部只调用getcontext函数。 swapIn成员函数根据用户指定调用swapcontext和t_threadFiber做切换或者和t_scheRunFiber做切换。 协程切入伪代码 swapOut成员函数协程切换回t_threadFiber或t_scheRunFiber时使用也是调用swapcontet。 协程切出伪代码 yieldToHold/yieldToReady设置协程状态然后调用swapOut。 下一章将介绍协程调度模块
感兴趣的同学可以阅读一下本文实现的源码https://github.com/LunarStore/lunar 本章完结