libgo 基础模块
libgo逻辑结构
libgo主要的功能模块主要包括:调度器( Scheduler )、处理器( Processer )、协程( Task )和一个FastSteadyClock。
其中 Scheduler -> Processer -> Task 三层逻辑结构实现了对协程( Task )的生命周期管理和调度和运行。
scheduler 功能
Processer 的创建和状态检查
Task 的创建
Processer 之间的负载均衡
Processer的功能
Task 的调度运行
Task 的资源回收
Scheduler
负责Processer(线程)管理,Task调度和负载均衡
一个std::thread类型的dispatchThread_(至少有一个,默认一个),任务:
定时检查processer运行超时(可配置,默认100ms),超时后将这个Processer的所有Task交给其他Processer处理
在processer之间进行task的负载均衡
std::thread类型的时钟线程FastSteadyClock,用于提供快速稳定的时钟访问,精度固定20ms
Processer
每一个processer对应一个std::thread
四个Task队列:runnableQueue,waitQueue,newQueue,gcQueue
新任务(新增的或steal来的任务)放入newQueue
Processer::process负责调度和运行协程代码;
runableQueue为空或没有可调度task就从newQueue补充,Task运行完成后被切换到done状态并进入gcQueue;
当gcQueue size>16则开始回收资源delete Task;
Task运行过程中由于资源得不到满足而且换到block状态,进入waitQueue,或主动放弃执行权限的Task仍然是runnable状态;
运行下一个runnableQueue中的Task,Task在被挂起时会将自己状态设置成block,并将自己放入waitQueue,不需要Processer::process将其放入waitQueue
负载均衡将在下面讲解
Task
Task有三种状态:runnable,block,done
Task调度流程
Task 的调度和运行是以 Processer 为单位进行的, 由 Processer::Process() 执行
Task 在 Processer::Process() 中大致的调度流程:
1. 从 runnableQueue 队头取 runningTask
2. runningTask 状态被设置成 TaskState::runnable
3. runningTask 被调度运行
4. runningTask 运行结束
a). 若状态为 TaskState::runnable , runingTask 取 runningTask->next , 若
runningTask 为空,则将 NewQueue 中的 Task 移动到 runnableQueue 中, 重新设置
runingTask 为 runningTask->next , 跳转到2.
b). 若状态为 TaskState::done , 则将 runningTask 从 runnableQueue 摘除, 放入
gcQueue , 当前取 runningTask->next 为 runningTask
c). 若状态为 TaskState::block , runingTask 取 runningTask->next ,跳转到2
https://blog.51cto.com/muhuizz/2328629