12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
三国霸业 战车-珍宝-觉醒-攻城掠地SF-全新玩法 免费玩新区 攻城掠地私服 进入游戏
手游私服盒子 各类免费游戏 0.1折送海量资源 各类手游私服 进入游戏
皇家MU2 《奇迹 2:传奇》韩国网禅公司《奇迹》正统续作。 3D锁视角Mmrpg 暗黑3+传奇+流放之路+奇迹 进入游戏
查看: 202|回复: 0

手把手实现一个协程/时间片轮转调度

[复制链接]
发表于 2020-5-11 10:16:49 | 显示全部楼层 |阅读模式
前言
其实是这样的,前不久突发奇想的想实现一个动画时钟。用的是经典的动画架构,两个线程分别负责渲染和数据运算。
但是呢,如果需要移植到单片机或者其他的低级环境(没有多线程),只能重新实现。不过还有一个办法,就是使用协程。

协程是啥(内容直接 C-c,C-v)
协程(Coroutine)编译器级的,进程(Process)和线程(Thread)操作系统级的
进程(Process)和线程(Thread)是os通过调度算法,保存当前的上下文,然后从上次暂停的地方再次开始计算,重新开始的地方不可预期,每次CPU计算的指令数量和代码跑过的CPU时间是相关的,跑到os分配的cpu时间到达后就会被os强制挂起,开发者无法精确的控制它们。
协程(Coroutine)是一种轻量级的用户态线程,实现的是非抢占式的调度,即由当前协程切换到其他协程由当前协程来控制。目前的协程框架一般都是设计成 1:N 模式。所谓 1:N 就是一个线程作为一个容器里面放置多个协程。那么谁来适时的切换这些协程?答案是有协程自己主动让出 CPU,也就是每个协程池里面有一个调度器,这个调度器是被动调度的。意思就是他不会主动调度。而且当一个协程发现自己执行不下去了(比如异步等待网络的数据回来,但是当前还没有数据到),这个时候就可以由这个协程通知调度器,这个时候执行到调度器的代码,调度器根据事先设计好的调度算法找到当前最需要 CPU 的协程。切换这个协程的 CPU 上下文把 CPU 的运行权交个这个协程,直到这个协程出现执行不下去需要等等的情况,或者它调用主动让出 CPU 的 API 之类,触发下一次调度。

时间片轮转调度
我不知道这是啥啊,噗,只是听上去很帅的样子。和协程相似,应用于底层(操作系统)的话也许名字就叫这个吧。

实现协程的方式
平时的话,其实有很多选择的嘛。比如说 Arduino 玩家会常玩的 ProtoThreads,比较轻量级,使用的 C 语言宏写成,占用资源低,易于移植。还有Libco啥的,其实没用过(捂脸。主要是如果无法理解协程的话,用起来会不怎么得(dei第三声)力。和线程以及RTOS的多任务不同,程序执行过程中不会中断去执行另一个任务。如果阻塞的一个协程的话,可能导致程序无法正常的表达。
自己实现一个协程的话,有助于理解底层原理,以及了解他的弊端。在以后的使用中,可以规避掉这种不正确的使用,写出更优质的代码。


我画了个示意图,这个是我个人的理解啊,我也不保证是完全对的。欢迎拍板砖。

根据上面的图,我们可以这样设计程序。

代码实现的是两个print字符串的过程,一个是1秒一个是2秒。类似多线程的效果。可以看到实现的功能很OjbK。之后,可以应用此协程库,来写点厉害的东西。
(本协程库已开源 https://github.com/JuncoJet/simCoroutines)


(动画帧数低,将就看,实际效果比这好多了)
这个是前些时候写的Cli的动画时钟,前言中提到的。我已经分别用多线程和自己写的协程来重新实现过了。两个版本都会打包,稍后可以附件中下载。




代码写的比较像Arduino中的代码,这样写有种亲切感,开开开玩笑。主要程序一旦运行就不会退出,结构很相似吧,所以就做了个模仿秀。

tgt[3]分别存储了3个协程触发的时间,程序loop中做时间轮询,时间到就触发代码块。
[C] 纯文本查看 复制代码void loop(){//负责时间片轮转 DWORD m=timeGetTime();if(m>=tgt[0]||!tgt[0])showTime();//协程0,显示时间if(m>=tgt[1]||!tgt[1])getTime();//协程1,获取时间if(m>=tgt[2]||!tgt[2])change();//协程2,递增数值Sleep(1);}

delay确定了下一次的执行时间,
[C] 纯文本查看 复制代码void delay(int t,int x){//负责更新时间         tgt[x]=(tgt[x]?tgt[x]:timeGetTime())+t;}
第一次运行tgt为空的话直接用timeGetTime()的值,之后直接累加。如果继续使用timeGetTime()的话会被协程执行时间延误从而受到影响,为避免协程运行时间产生偏差,所以我采用直接累加的方式。
其他功能,下载附件后自行研究吧,本章主讲协程。这个代码只是举个栗子!

协程的好处
协程有三宝,双手和大脑(雾
协程占用资源低,可以应用于一些环境苛刻的地方,如大多数的8位单片机。
协程是一种(新的)程序的思想,单线程写着无聊了,可以尝试另一种写法。
协程还能应用于VB、Ruby(不黑你的假多线程)之类的无法完美支持多线程的程序中使用。

内容比较干,比较初级,欢迎大家留言深入讨论。CliClock.zip
14.52 KB, 下载次数: 18, 下载积分: 吾爱币 -1 CB


来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-11-28 23:07 , Processed in 0.078125 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表