原文传送门

FRunnable & FRunnableThread

FRunnable提供了最为原始的线程支持,类似std::Thread,虽然没那么优雅,但是功能略多于std::Thread

  • FRunnable—-承载业务逻辑
    • +[f] Init : 初始化,可以失败
    • +[f] Run : 线程运行函数,返回退出代码
    • +[f] Stop : 提前终止这个线程
    • +[f] Exit : 进行退出前的清理
    • +[f] GetSingleThreadInterface : 平台不支持多线程时的FeedBack策

  • FRunnableThread—-线程实体
    • -[sm] RunnableTlsSlot : TLS Slot, 用于实现动态的Thread Local
    • ——————————-split——————————-
    • -[m] ThreadName : 线程名
    • -[m] Runnalbe : 具体执行的Runnable对象
    • -[m] ThreadInitSyncEvent : 主线程等待事件,确保Init完成
    • -[m] TlsInstances : Thread local变量
    • -[m] ThreadPriority : 线程优先级
    • -[m] ThreadID : 线程ID
    • ——————————-split——————————-
    • +[f] GetTlsSlot : 拿到 TLS Slot
    • +[f] SetThreadPriority : 设置线程优先权
    • +[f] Suspend : 挂起或恢复线程
    • +[f] Kill : 杀死线程,可选等待
    • +[f] WaitForCompletion : 等待线程完成
    • ——————————-split——————————-
    • +[sf] Create : 创建一个线程来运行Runnable

  • FThreadManager—-线程管理器
    • -[m] Threads : 所有的线程
    • +[f] AddThread : 把线程添加到管理,在线程创建的时候既调用
    • +[f] RemoveThread : 移除线程
    • +[f] Tick : 对于Fake线程,会在Tick中执行
    • +[f] GetThreadName : 通过Id得到线程名
    • +[f] IsInitialized : 是否完成初始化
    • +[f] ForEachThread : 遍历线程
    • +[sf] Get : 得到单例

  • 用法
    FRunnable * Runnable = new MyRunnable();
    FRunnableThread* RunnableThread = FRunnableThread::Create(Runnable, TEXT("MyThread"));

AsynTask

AsynTask实现了池化的任务,任务之间不支持依赖关系,但是可以回收,Task由工作线程执行

  • IQueuedWork—-Work的上层抽象
    • +[f] DoThreadedWork : 执行Work
    • +[f] Abandon : 放弃执行Work,仅从线程池调用

  • FQueuedThread—-假的Thread,真的Runnable
    • -[m] DoWorkEvent : 用于唤醒Worker工作
    • -[m] TimeToDie : 用于告知Worker退出线程
    • -[m] QueuedWork : 当前的Work
    • -[m] OwningThreadPool : 依附的ThreadPool
    • -[m] Thread : 依附的线程
    • ——————————-split——————————-
    • -[f] Run : 实现的Run接口函数,内部是一个以TimeToDie为条件的循环,在没有Work的时候执行等待,ThreadPool填入Work并环境,当完成work时,会向线程池申请或将自己返丢回线程池
    • +[f] Create : 创建一个真正的线程并依附上去,然后加到线程池内
    • +[f] KillThread : 杀死线程,在真正杀死之前会阻塞等待
    • +[f] DoWork : 执行Work,没什么花哨

  • FQueuedThreadPool—-线程池
    • +[f] Create : 创建指定数量的线程
    • +[f] Destroy : 销毁线程池
    • +[f] AddQueuedWork : 添加Work
    • +[f] RetractQueuedWork : 尝试回收Work
    • +[f] GetNumThreads : 得到工作线程数量
    • ——————————-split——————————-
    • -[sf] Allocate : 创建一个线程池(FQueuedThreadPoolBase)
    • -[sm] OverrideStackSize : 创建线程时的最小栈大小

  • FAsyncTask—-方便使用的套壳模板
    • -[m] Task : 模板Task
    • -[m] WorkNotFinishedCounter : 用于标记Task是否完成
    • -[m] DoneEvent : 用于等待Task完成的Event
    • -[m] QueuedPool : Task依附的线程池
    • ——————————-split——————————-
    • -[f] DestroyEvent : 内部使用,回收Event
    • -[f] Start : 内部使用,开始执行Task
    • -[f] DoWork : 内部使用,执行Task,执行完后会将Finished计数减一
    • -[f] FinishThreadedWork : 内部使用,触发DoneEvent
    • -[f] DoThreadWork : 内部使用,依次调用以上两个函数
    • -[f] Abandon : 内部使用,丢弃任务
    • -[f] CheckIdle : 内部使用,检测是否是独立任务
    • -[f] SyncCompletion : 内部使用,等待任务完成
    • -[f] Init : 初始化,仅做置空
    • +[f] GetTask : 获取Task引用
    • +[f] StartSynchronousTask : 启动阻塞任务
    • +[f] StartBackgroundTask : 启动异步任务
    • +[f] EnsureCompletion : 确保Task执行完成,可选立刻阻塞执行
    • +[f] Cancel :收回Task
    • +[f] WaitCompletionWithTimeout : 带有超时的等待完成
    • +[f] IsDone : 任务是否完成,会自动重置Event以便重用
    • +[f] IsWorkDone : 任务是否完成,但是不会重置任何状态
    • +[f] IsIdle : 任务是否并没有Start或没有完成
    • ——————————-split——————————-
    • TTask需要实现的函数
      • CanAbandon : 是否可以被丢弃
      • Abandon : 丢弃任务
      • DoWork : 执行体
      • GetStatId : 得到任务的StatId

  • FNonAbandonableTask—-无法被丢弃的Task
    • 实现了CanAbandonAbandon函数,继承它的task只需要实现DoWork和GetStatId即可

  • 用法
    
    class MyTask : public FNonAbandonableTask
    {
    public:
    void DoWork() { xxxx }
    FORCEINLINE TStatId GetStatId() const
    {
        RETURN_QUICK_DECLARE_CYCLE_STAT(MyTask, STATGROUP_ThreadPoolAsyncTasks);
    }
    }
    void Example()
    {
    FAsyncTask<MyTask> Task;
    // start up
    Task->StartBackgroundTask();
    // xxxx Other operations 
    // wait complet 
    Task->EnsureCompletion();
    }


### TaskGraph
> TaskGraph

- **FSingleThreadRunnable----Fake线程**
    - **+[f] Tick** : 在单线程情况下调用Tick来模拟多线程

--------------------------------------------------------------------------

- **FWorkerThread----帮助结构体**
    - **+[m] TaskGraphWorker** : Task工作线程
    - **+[m] RunnableThread** : 实体线程
    - **+[m] bAttached** : Task工作线程是否Attach到实体线程上
- **FTaskThreadBase----Task工作线程基类, Runnable**
    - **-[m] ThreadId** : ENamedThreads的枚举用来标识当前线程
    - **-[m] PerThreadIDTLSSlot** : TLS Slot
    - **-[m] IsStalled** : 用于标记是否失速 ?
    - **-[m] NewTasks** : 当前线程得到的新任务
    - **-[m] OwnerWorker** : 持有本工作线程的Worker
    - -------------------------------split-------------------------------
    - **+[f] SetUp** : 设置一些基础信息
    - **+[f] InitializeForCurrentThread** : 仅调用一次,设置TLS变量
    - **+[f] GetThreadId** : 得到ThreadID
    - **+[f] ProcessTasksUntilQuit** : 一直执行Task直到退出
    - **+[f] ProcessTasksUntilIdle** : 一直执行Task直到Idle被调用
    - **+[f] EnqueueFromThisThread** : 入队Task,假定是从当前线程调用
    - **+[f] EnqueueFromOtherThread** : 入队Task,假定从其它线程调用
    - **+[f] RequestQuit** : 请求结束线程 
    - **+[f] WakeUp** : 唤醒线程
    - **+[f] IsProcessingTasks** : 是否在处理任务
- **FNamedTaskThread----命名线程**
    - 从自己的工作队列中提取Task
- **FTaskThreadAnyThread----工作线程**
    - 从整体的Task池中提取Task

--------------------------------------------------------------------------

- **FTaskGraphInterface** : TaskGraph系统对外接口
- **FTaskGraphImplementation** : TaskGraphInterface的实现体
- **FBaseGraphTask** : 所有Task的基类
- **FGraphEvent** : Task之间的通知机制,用于形成依赖网络
- **TGraphTask** : 方便使用的模板

### Reference
- [《Exploring in UE4》多线程机制详解](https://zhuanlan.zhihu.com/p/38881269)
- [UE4 C++基础教程 - 多线程](https://zhuanlan.zhihu.com/p/133921916)

发表回复