Catalogue
前言
协程是Cyber-RT的实现任务轮转的最小单位,是处理数据回调的运行模块。协程可以理解为“可以暂停”的函数,相比于线程,其具有中断可恢复的特性,那么只需要在开一个全局的数组存储所有的协程,在协程中断时,不断轮转调用下一个协程继续运行即可达到类似线程的效果。
为什么选用协程,因为基于协程的特性再加上Cyber中枢调度Scheduler
的线程调度,可以避免回调时由于阻塞导致其他回调不能被执行的情况;此外,协程是在用户态来完成上下文切换的,所以切换耗时只有区区100ns多一些,比进程切换要高30倍。
Cyber/croutine目录
1 | ├── BUILD |
Croutine类图
...
结构图
协程的创建
Cyber-RT中有两个地方创建了协程:
Component
的初始化Reader
的初始化
两处地方的创建大同小异,这里给出Component<M0, NullType, NullType, NullType>::Initialize
函数中关于创建协程的代码片段:
1 | template <typename M0> |
其流程大概是这样:
- 写出一个lambda函数,内部进行msg的回调处理
- 构造一个
DataVistor
- 将lambda函数和创建的
DataVistor
一并作为参数,用于创建协程工厂croutine::RoutineFactory - 将协程工厂作为参数,调用中枢调度Scheduler::CreateTask(...)函数
Why RoutineFactory?
看到上面的代码片段可能会觉得奇怪,为什么需要协程工厂这一层,直接创建一个协程不好吗?
这其实是一种封装,假设我们直接创建一个协程,那么需要传入一个回调函数,用于处理msg,然而Cyber-RT一共考虑了1-4种msg的情况,那么创建协程时传入的回调函数的参数就有4种情况,这使得接口不能统一。使用协程工厂就是为了对4种情况进行封装,并统一接口,即创建协程时只需要把协程工厂传入作为参数即可。