GF_Task Created 2023-05-01 | Updated 2023-05-01
三个核心概念
TaskPool:驱动task
Task:某个任务的抽象,但是不负责任务具体执行
Agent:干活的代理(不过对于Resource来说真正干活的是内部的helper)
TaskPool中维护三个数据结构:
这个T就是Task定义 比如TaskPool m_TaskPool;
1 2 3 private readonly Stack<ITaskAgent<T>> m_FreeAgents; private readonly GameFrameworkLinkedList<ITaskAgent<T>> m_WorkingAgents; private readonly GameFrameworkLinkedList<T> m_WaitingTasks;
实际上的任务具体执行是通过agent,当前正在跑的总任务数会被此限制 多出的任务会通过等待队列等待
增加task 从后向前,根据优先级找到需要插队的位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public void AddTask (T task ){ LinkedListNode<T> current = m_WaitingTasks.Last; while (current != null ) { if (task.Priority <= current.Value.Priority) { break ; } current = current.Previous; } if (current != null ) { m_WaitingTasks.AddAfter(current, task); } else { m_WaitingTasks.AddFirst(task); } }
增加Agent 1 2 3 4 5 public void AddAgent (ITaskAgent<T> agent ){ agent.Initialize(); m_FreeAgents.Push(agent); }
关于LoadResourceAgent 当taskPool Update的时候 ,会尝试Start某个空闲的Agent。 所以资源加载的Agent大部分逻辑也位于Start中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public StartTaskStatus Start (LoadResourceTaskBase task ){ ..... if (!m_Task.IsScene) { AssetObject assetObject = m_ResourceLoader.m_AssetPool.Spawn(m_Task.AssetName); if (assetObject != null ) { OnAssetObjectReady(assetObject); return StartTaskStatus.Done; } } ResourceObject resourceObject = m_ResourceLoader.m_ResourcePool.Spawn(resourceName); if (resourceObject != null ) { OnResourceObjectReady(resourceObject); return StartTaskStatus.CanResume; } if (resourceInfo.LoadType == LoadType.LoadFromFile) { ...... m_Helper.ReadFile(fullPath); } }
此处会构建两个Object:
AssetObject : 表示Asset (从AssetBoundle中加载出来的)
ResourceObject : 表示AssetBoundle
从OnResourceObjectReady进入:
1 2 3 4 5 6 7 8 9 10 private void OnResourceObjectReady (ResourceObject resourceObject ){ m_Task.LoadMain(this , resourceObject); } public void LoadMain (LoadResourceAgent agent, ResourceObject resourceObject ){ m_ResourceObject = resourceObject; agent.Helper.LoadAsset(resourceObject.Target, AssetName, AssetType, IsScene); }
轮询:
1 2 3 4 5 6 7 8 9 10 public void Update (float elapseSeconds, float realElapseSeconds ){ if (m_Paused) { return ; } ProcessRunningTasks(elapseSeconds, realElapseSeconds); ProcessWaitingTasks(elapseSeconds, realElapseSeconds); }
ProcessRunningTasks
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 LinkedListNode<ITaskAgent<T>> current = m_WorkingAgents.First; while (current != null ){ T task = current.Value.Task; if (!task.Done) { current.Value.Update(elapseSeconds, realElapseSeconds); current = current.Next; continue ; } LinkedListNode<ITaskAgent<T>> next = current.Next; current.Value.Reset(); m_FreeAgents.Push(current.Value); m_WorkingAgents.Remove(current); ReferencePool.Release(task); current = next; }
遍历warking链表,如果发现有任务完成了,移除,并将agent加入FeeeAgents (执行任务是调用TRaskAgent.Update)
ProcessWaitingTasks 遍历waiting链表,如果FreeAgents中有可用agent,从waiting中取个任务让agent来做,并加入working中 Remove:分别处理等待队列和工作队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public bool RemoveTask (int serialId ){ foreach (T task in m_WaitingTasks) { if (task.SerialId == serialId) { m_WaitingTasks.Remove(task); ReferencePool.Release(task); return true ; } } foreach (ITaskAgent<T> workingAgent in m_WorkingAgents) { if (workingAgent.Task.SerialId == serialId) { T task = workingAgent.Task; workingAgent.Reset(); m_FreeAgents.Push(workingAgent); m_WorkingAgents.Remove(workingAgent); ReferencePool.Release(task); return true ; } } return false ; }