mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +08:00
- Refactor frame converter implementation - Update mp4 track to use ICodex - General refactoring and code improvements 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
任务系统概要
任务的启动
任务通过调用父任务的 AddTask 来启动,此时会进入队列中等待启动,父任务的 EventLoop 会接受到子任务,然后调用子任务的 Start 方法进行启动操作
EventLoop 的初始化
为了节省资源,EventLoop 在没有子任务时不会创建协程,一直等到有子任务时才会创建,并且如果这个子任务也是一个空的 Job(即没有 Start、Run、Go)则仍然不会创建协程。
EventLoop 停止
为了节省资源,当 EventLoop 中没有待执行的子任务时,需要退出协程。EventLoop 会在以下情况退出:
- 没有待处理的任务且没有活跃的子任务,且父任务的 keepalive() 返回 false
- EventLoop 的状态被设置为停止状态(-1)
任务的停止
主动停止某个任务
调用任务的 Stop 方法即可停止某个任务,此时该任务会由其父任务的 eventLoop 检测到 context 取消信号然后开始执行任务的 dispose 来进行销毁
任务的意外退出
当任务的 Run 返回错误,或者 context 被取消时,任务会退出,最终流程会同主动停止一样
父任务停止
当父任务停止并销毁时,会按照以下步骤处理子任务:
步骤
- 设置 EventLoop 的状态为停止状态:调用
stop()方法设置 status = -1,防止继续添加子任务 - 激活 EventLoop 处理剩余任务:调用
active()方法,即使状态为 -1 也能处理剩余的子任务 - 停止所有子任务:调用所有子任务的 Stop 方法
- 等待子任务销毁完成:等待 EventLoop 处理完所有子任务的销毁工作
设计要点
- EventLoop 的
active()方法允许在状态为 -1 时调用,以确保剩余的子任务能被正确处理 - 使用互斥锁保护状态转换,避免竞态条件
- 先停止再处理剩余任务,确保不会添加新的子任务
竞态条件处理
为了确保任务系统的线程安全,我们采取了以下措施:
状态管理
- 使用
sync.RWMutex保护 EventLoop 的状态转换 add()方法使用读锁检查状态,防止在停止后添加新任务stop()方法使用写锁设置状态,确保原子性
EventLoop 生命周期
- EventLoop 只有在状态从 0(ready)转换到 1(running)时才启动新的 goroutine
- 即使状态为 -1(stopped),
active()方法仍可被调用以处理剩余任务 - 使用
hasPending标志和互斥锁跟踪待处理任务,避免频繁检查 channel 长度
任务添加
- 添加任务时会检查 EventLoop 状态,如果已停止则返回
ErrDisposed - 使用
pendingMux保护hasPending标志,避免竞态条件