虚幻4 Task小记
来源:互联网 发布:守望先锋显卡优化 编辑:程序博客网 时间:2024/05/16 23:39
TGraphTask类里面有一个FConstructor类,用来创建TGraphTask。
FGraphEventRef ConstructAndDispatchWhenReady(T&&... Args){new ((void *)&Owner->TaskStorage) TTask(Forward<T>(Args)...);return Owner->Setup(Prerequisites, CurrentThreadIfKnown);}
这个就直接字面意思,创建一个TGraphTask,但是等他的prerequisites都触发了,才把这个任务分发。也就是进入队列。
FConstructor(TGraphTask* InOwner, const FGraphEventArray* InPrerequisites, ENamedThreads::Type InCurrentThreadIfKnown): Owner(InOwner), Prerequisites(InPrerequisites), CurrentThreadIfKnown(InCurrentThreadIfKnown){}
创建的时候可以传入一个EVENT数组,这个Constructor创建TGraphTask时候回判断需求的event是否都已经触发了,如果没有触发,那就先不创建。
void SetupPrereqs(const FGraphEventArray* Prerequisites, ENamedThreads::Type CurrentThreadIfKnown, bool bUnlock){checkThreadGraph(!TaskConstructed);TaskConstructed = true;TTask& Task = *(TTask*)&TaskStorage;SetThreadToExecuteOn(Task.GetDesiredThread());int32 AlreadyCompletedPrerequisites = 0;if (Prerequisites){for (int32 Index = 0; Index < Prerequisites->Num(); Index++){check((*Prerequisites)[Index]);if (!(*Prerequisites)[Index]->AddSubsequent(this)){AlreadyCompletedPrerequisites++;}}}PrerequisitesComplete(CurrentThreadIfKnown, AlreadyCompletedPrerequisites, bUnlock);}
PrerequisitesComplete
函数就是判断是否所有event都触发过的函数。TGraphTask里面有一个变量
/** A reference counted pointer to the completion event which lists the tasks that have me as a prerequisite. **/FGraphEventRefSubsequents;
当这个任务执行完时候,会触发这个event,这个event保存了对于他有依赖的所有FConstructor,是一个数组,
然后会告诉constructor,这个event触发了,看看是不是可以执行了。
然后一堆constructor有的发现确实所需要的event都触发了,就创建一个task,有的发现还有没有触发的event,就不创建,继续等待。
这个就是event触发时候调用的函数。
/** *"Complete" the event. This grabs the list of subsequents and atomically closes it. Then for each subsequent it reduces the number of prerequisites outstanding and if that drops to zero, the task is queued. *@param CurrentThreadIfKnown if the current thread is known, provide it here. Otherwise it will be determined via TLS if any task ends up being queued.**/CORE_API void DispatchSubsequents(TArray<FBaseGraphTask*>& NewTasks, ENamedThreads::Type CurrentThreadIfKnown = ENamedThreads::AnyThread);
void FGraphEvent::DispatchSubsequents(TArray<FBaseGraphTask*>& NewTasks, ENamedThreads::Type CurrentThreadIfKnown){if (EventsToWaitFor.Num()){// need to save this first and empty the actual tail of the task might be recycled faster than it is cleared.FGraphEventArray TempEventsToWaitFor;Exchange(EventsToWaitFor, TempEventsToWaitFor);// create the Gather...this uses a special version of private CreateTask that "assumes" the subsequent list (which other threads might still be adding too).DECLARE_CYCLE_STAT(TEXT("FNullGraphTask.DontCompleteUntil"),STAT_FNullGraphTask_DontCompleteUntil,STATGROUP_TaskGraphTasks);TGraphTask<FNullGraphTask>::CreateTask(FGraphEventRef(this), &TempEventsToWaitFor, CurrentThreadIfKnown).ConstructAndDispatchWhenReady(GET_STATID(STAT_FNullGraphTask_DontCompleteUntil), ENamedThreads::HiPri(ENamedThreads::AnyThread));return;}#if USE_NEW_LOCK_FREE_LISTSbComplete = true;int32 SpinCount = 0;while (true){FBaseGraphTask* NewTask = SubsequentList.Pop();if (!NewTask){if (SubsequentList.CloseIfEmpty()){break;}LockFreeCriticalSpin(SpinCount);continue;}NewTask->ConditionalQueueTask(CurrentThreadIfKnown);}#elseSubsequentList.PopAllAndClose(NewTasks);for (int32 Index = NewTasks.Num() - 1; Index >= 0 ; Index--) // reverse the order since PopAll is implicitly backwards{FBaseGraphTask* NewTask = NewTasks[Index];checkThreadGraph(NewTask);NewTask->ConditionalQueueTask(CurrentThreadIfKnown);}NewTasks.Reset();#endif}
NewTask->ConditionalQueueTask(CurrentThreadIfKnown);
能看到最后这个函数,就是让Task判断是否要进入队列了。
<pre name="code" class="cpp">/** *An indication that a prerequisite has been completed. Reduces the number of prerequisites by one and if no prerequisites are outstanding, it queues the task for execution. *@param CurrentThread; provides the index of the thread we are running on. This is handy for submitting new taks. Can be ENamedThreads::AnyThread if the current thread is unknown. **/void ConditionalQueueTask(ENamedThreads::Type CurrentThread){if (NumberOfPrerequistitesOutstanding.Decrement()==0){QueueTask(CurrentThread);}}
就是让TGraphTask自己看看是不是可以执行了。
PrerequisitesComplete
/** An aligned bit of storage to hold the embedded task **/TAlignedBytes<sizeof(TTask),ALIGNOF(TTask)> TaskStorage;
其实就是创建了一个Task,但是没有和我们自己宏创建的那个类有关联,就是创建了一个空壳。
ConstructAndDispatchWhenReady
才是吧自己宏创建的那个类实例化,放在TGraphTask的一个变量里面。
当执行这个task时候,执行自己的那个类的DoTask()
0 0
- 虚幻4 Task小记
- 虚幻4 TaskGraph小记
- 虚幻4 Task的创建和执行
- 虚幻4 主线程一直向渲染线程发送Task
- 虚幻4引擎
- 虚幻4引擎
- 虚幻4的Style
- 虚幻4 Editor 编程
- 虚幻4 蒙太奇
- 虚幻4编码规范
- 虚幻4目录结构
- 虚幻4 反射
- 虚幻4 材质基础
- 虚幻4 Function Library
- 虚幻4 碰撞过滤
- 虚幻4 笔记
- 虚幻4编码规范
- 虚幻4 SCOPE_CYCLE_COUNTER
- SSH2+ajax+jsp登录源码
- 排序算法之直接插入排序和希尔排序
- leetcode 80 Remove Duplicates from Sorted Array II
- solr5.5之从数据库中导入数据并建立索引
- clock()函数在多线程时的问题
- 虚幻4 Task小记
- ahu-730-幸运抽奖
- 关于RunLoop的几点个人看法
- 回文素数的Java实现代码
- android对字段的验证
- 网络流题集
- Raising Modulo Numbers(数论)
- 【Western Digital】固件区学习之缺陷表(30、31、32、33、34、35、36模块)
- 随笔知识2