Tick与GraphTask

来源:互联网 发布:数据修炼系统顶点 编辑:程序博客网 时间:2024/06/10 15:20

一、GraphTask(任务图)

UE4的GraphTask是一个很重要的框架,不管是渲染或者是Tick任务管理,都用到了GraphTask,本篇文章就主要讲解GraphTask在Tick中的使用。GraphTask主要有下面几个类:

1、FBaseGraphTask

这个类是TGraphTask的基类,其中最重要的成员变量是
FThreadSafe CounterNumberOfPrerequistitesOutstanding;
这是一个线程安全的计数器,用于保存Prerequistite(先行任务)的个数,这个计数器是在构造函数中初始化的
    FBaseGraphTask(#if USE_VIRTUAL_BYPASS        TExecuteTask InExecuteTaskPtr,#endif        int32 InNumberOfPrerequistitesOutstanding        )        : ThreadToExecuteOn(ENamedThreads::AnyThread)        , NumberOfPrerequistitesOutstanding(InNumberOfPrerequistitesOutstanding + 1) // + 1 is not a prerequisite, it is a lock to prevent it from executing while it is getting prerequisites, one it is safe to execute, call PrerequisitesComplete    {#if USE_VIRTUAL_BYPASS        ExecuteTaskPtr = InExecuteTaskPtr;#endif        checkThreadGraph(LifeStage.Increment() == int32(LS_Contructed));    }
可以看到这个构造函数在初始化NumberOfPrerequistitesOutstanding的值的时候会比传入的先行任务的个数多加1,这主要是给该任务上锁,在整个任务构造完成后,或者该任务需要马上执行,就会对该任务解锁,即NumberOfPrerequistitesOutstanding减1。FBaseGraphTask主要实现都是围绕NumberOfPrerequistitesOutstanding展开的,每执行完一个先行任务,该先行任务的所有后继任务的NumberOfPrerequistitesOutstanding就减1,当NumberOfPrerequistitesOutstanding为0的时候就将该任务放到线程中去执行,具体可以参考ConditionalQueueTask()和QueueTask()这两个函数的实现

2、TGraphTask

这个类继承于FBaseGraphTask,是一个模板类,所有模板都必须实现DoTask()函数,该类最重要的成员有两个
TAlignedBytes<sizeof(TTask),ALIGNOF(TTask)> TaskStorage;FGraphEventRef              Subsequents;
TaskStorage存储了具体的模板任务(该模板必须实现DoTask()函数),当调用ExecuteTask()的时候就会调用TTask::DoTask(),ExecuteTask()是被FBaseGraphTask::Execute()所调用,当线程从任务队列中取出任务后,就会执行FBaseGraphTask::Execute()。Subsequents是FGraphEventRef类型,实际存储的就是一个FBaseGraphTask列表,就是该任务的所有后继任务,当当前任务执行完毕,就是通过这个列表通知所有的后继任务的NumberOfPrerequistitesOutstanding减1的,总的来说,一个TGraphTask只存放了先行任务的个数,但是存放了所有后继任务的指针,这样,整个任务图就像一个有向无环图(或者像一个森林树形结构),任务从根节点开始,有序的执行下去

3、FGraphEvent

这个类最主要的成员变量为
/** Threadsafe list of subsequents for the event **/TClosableLockFreePointerListUnorderedSingleConsumer<FBaseGraphTask, 0>      SubsequentList;
存放的是FBaseGraphTask列表,该类主要是TGraphTask用来存放后继任务(参看TGraphTask的Subsequents成员变量)。

4、FTaskGraphInterface

这是一个接口,主要用来管理GraphTask的线程。这个接口有一个静态函数Get(),返回的是FTaskGraphImplementation的实例,是单例模式。
static FTaskGraphImplementation* TaskGraphImplementationSingleton = NULL;FTaskGraphInterface& FTaskGraphInterface::Get(){    checkThreadGraph(TaskGraphImplementationSingleton);    return *TaskGraphImplementationSingleton;}

5、FTaskGraphImplementation

FTaskGraphImplementation是接口FTaskGraphInterface的实现,最主要的成员变量有
FWorkerThread       WorkerThreads[MAX_THREADS];
WorkerThreads被用来存放所有的工作线程,比如游戏主线程、渲染线程等,线程的创建是在FTaskGraphImplementation构造函数中完成的。任务入队的函数调用顺序为FBaseGraphTask::QueueTask()→FTaskGraphImplementation::QueueTask()→FNamedTaskThread::EnqueueFromThisThread(),这样就会将一个TGraphTask<TTask>实例放入线程对应的优先级队列中,并被执行。
原创粉丝点击