Files
monibuca/pkg/task
langhuihui 8a9fffb987 refactor: frame converter and mp4 track improvements
- 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>
2025-08-28 19:55:37 +08:00
..
2024-10-06 17:56:11 +08:00

任务系统概要

任务的启动

任务通过调用父任务的 AddTask 来启动,此时会进入队列中等待启动,父任务的 EventLoop 会接受到子任务,然后调用子任务的 Start 方法进行启动操作

EventLoop 的初始化

为了节省资源EventLoop 在没有子任务时不会创建协程,一直等到有子任务时才会创建,并且如果这个子任务也是一个空的 Job即没有 Start、Run、Go则仍然不会创建协程。

EventLoop 停止

为了节省资源,当 EventLoop 中没有待执行的子任务时需要退出协程。EventLoop 会在以下情况退出:

  1. 没有待处理的任务且没有活跃的子任务,且父任务的 keepalive() 返回 false
  2. EventLoop 的状态被设置为停止状态(-1

任务的停止

主动停止某个任务

调用任务的 Stop 方法即可停止某个任务,此时该任务会由其父任务的 eventLoop 检测到 context 取消信号然后开始执行任务的 dispose 来进行销毁

任务的意外退出

当任务的 Run 返回错误,或者 context 被取消时,任务会退出,最终流程会同主动停止一样

父任务停止

当父任务停止并销毁时,会按照以下步骤处理子任务:

步骤

  1. 设置 EventLoop 的状态为停止状态:调用 stop() 方法设置 status = -1防止继续添加子任务
  2. 激活 EventLoop 处理剩余任务:调用 active() 方法,即使状态为 -1 也能处理剩余的子任务
  3. 停止所有子任务:调用所有子任务的 Stop 方法
  4. 等待子任务销毁完成:等待 EventLoop 处理完所有子任务的销毁工作

设计要点

  • EventLoop 的 active() 方法允许在状态为 -1 时调用,以确保剩余的子任务能被正确处理
  • 使用互斥锁保护状态转换,避免竞态条件
  • 先停止再处理剩余任务,确保不会添加新的子任务

竞态条件处理

为了确保任务系统的线程安全,我们采取了以下措施:

状态管理

  • 使用 sync.RWMutex 保护 EventLoop 的状态转换
  • add() 方法使用读锁检查状态,防止在停止后添加新任务
  • stop() 方法使用写锁设置状态,确保原子性

EventLoop 生命周期

  • EventLoop 只有在状态从 0ready转换到 1running时才启动新的 goroutine
  • 即使状态为 -1stoppedactive() 方法仍可被调用以处理剩余任务
  • 使用 hasPending 标志和互斥锁跟踪待处理任务,避免频繁检查 channel 长度

任务添加

  • 添加任务时会检查 EventLoop 状态,如果已停止则返回 ErrDisposed
  • 使用 pendingMux 保护 hasPending 标志,避免竞态条件