三个核心概念

  1. TaskPool:驱动task
  2. Task:某个任务的抽象,但是不负责任务具体执行
  3. Agent:干活的代理(不过对于Resource来说真正干活的是内部的helper)

TaskPool中维护三个数据结构:

  • 可用Agent堆
  • 正在等待的任务
  • 正在运行的任务

这个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)
{
//此处可能调用OnLoadDependencyAsset
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:

  1. AssetObject : 表示Asset (从AssetBoundle中加载出来的)
  2. 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);
}
  1. 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)

  1. 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;
}