自研C++协程网络框架(一)

        从事C++多年,没有留下什么。最近突然想写一些东西,为自己的程序员生涯留下一些痕迹。想到哪儿写到哪儿吧。

具体的代码可参考 taro-dady/co_taro: coroutine framework (github.com)

一 、什么是协程

        以我个人的粗浅理解,协程就是把线程的时间片进行拆分。本来一个线程在操作系统的分配下得到的时间片,又被协程拆分了。线程的调度要靠内核,而协程的调度只需要在用户态就可以了。

                                ​​​​    

二、协程使用场景

任务的切换效率:

不同进程间的线程切换 < 同进程的线程切换 < 同线程的协程切换

任务分类:

a. 计算密集型

计算密集型的任务需要长时间使用CPU,因此并不太适合使用协程,可能一个线程时间片都不够计算使用就没有必要再关注切换的问题了

b. IO密集型

IO密集型的任务CPU使用的时间短,等待IO就绪的时间长,这种情况下使用协程是一个较好的选择

三、协程的核心概念

协程的核心概念有两个: 第一是协程切换方法,第二是协程的调度策略

3.1 协程切换

LinuxWindows
ucontext(C)fiber(C)
setjmp/longjmpsetjmp/longjmp
寄存器(汇编)寄存器(汇编)

具体的分析就不多做赘述了,网上分析的文章很多,各位自行查阅即可。我在此选择了汇编操作寄存器的方案。

协程的栈:用来保存被切换出去的协程的寄存器的值,当该协程被调度时将栈里的数据还原到寄存器中

有栈协程静态栈:每个协程单独的固定大小栈。好处是比较独立,坏处是大小不好分配
共享栈:多个协程共享一个栈,协程自身的栈数据保存在自己申请的内存中,需要切换时把自己内存中的数据拷贝到共享栈中,完成协程切换

虚拟栈:进程申请的内存并不会立即映射成物理内存,而是仅管理于虚拟内存中,真正对其读写时会触发缺页中断,此时才会映射为物理内存

比如: 用malloc申请一个内存比如2M,申请完成后并没有在物理上实际使用2M,只有在使用时才会进行实际的分配内存。内存分配是按页分配的(4K),也就是最多也就冗余4K - 1的内存

无栈协程

无栈协程有点像状态机,全程只用了一个栈,把一个协程拆分成很多小块,这些小块的入口只有一个,然后通过改变state的值来实现协程的不同逻辑。这种实现无需保存协程的栈帧,可以节省内存提高速度,但是不能实现协程的任意切换(C++20用的是无栈协程)

int state = 0;

if ( 0 == state ){

        func1();

}else if( 2 == state ){

        func2();

}

void func1(){ state = 1;  ....}

void func2(){ state = 0; .... };

3.2 协程调度

3.2.1 非对称协程

非对称协程指的是协程之间有绑定调用关系,从一个协程切换到新协程后,新协程就只能返回到原调用方协程。

3.2.2 对称协程

每个协程的地位关系都是平等的,可以由任意一个协程切换到任意另外一个协程。

 3.2.3 协程调度器

a.  不跨线程的协程调度

协程只会被一个线程调度,这样的好处是可以不考虑线程并发的问题,用同步的方式实现异步编程模型。坏处是协程的分配不均匀,导致某些线程负载很高,而某些负载很低的情况发生

b. 跨线程的协程调度

协程会被多个线程调度,好处是可以平衡线程负载,坏处是协程需要考虑线程并发竞争问题

c. 混合协程调度

每个CPU都有自己的协程队列,当本地的协程队列没有协程时,从全局协程队列中取协程到本地队列

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值