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
- 实现了CanAbandon和Abandon函数,继承它的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)