//------------------------------------------------------------ // Game Framework // Copyright © 2013-2021 loyalsoft. All rights reserved. // Homepage: http://www.game7000.com/ // Feedback: http://www.game7000.com/ //------------------------------------------------------------ using System.Collections.Generic; namespace GameFramework { /// /// 任务池。 /// /// 任务类型。 internal sealed class TaskPool where T : TaskBase { private readonly Stack> m_FreeAgents; private readonly GameFrameworkLinkedList> m_WorkingAgents; private readonly GameFrameworkLinkedList m_WaitingTasks; private bool m_Paused; /// /// 初始化任务池的新实例。 /// public TaskPool() { m_FreeAgents = new Stack>(); m_WorkingAgents = new GameFrameworkLinkedList>(); m_WaitingTasks = new GameFrameworkLinkedList(); m_Paused = false; } /// /// 获取或设置任务池是否被暂停。 /// public bool Paused { get { return m_Paused; } set { m_Paused = value; } } /// /// 获取任务代理总数量。 /// public int TotalAgentCount { get { return FreeAgentCount + WorkingAgentCount; } } /// /// 获取可用任务代理数量。 /// public int FreeAgentCount { get { return m_FreeAgents.Count; } } /// /// 获取工作中任务代理数量。 /// public int WorkingAgentCount { get { return m_WorkingAgents.Count; } } /// /// 获取等待任务数量。 /// public int WaitingTaskCount { get { return m_WaitingTasks.Count; } } /// /// 任务池轮询。 /// /// 逻辑流逝时间,以秒为单位。 /// 真实流逝时间,以秒为单位。 public void Update(float elapseSeconds, float realElapseSeconds) { if (m_Paused) { return; } ProcessRunningTasks(elapseSeconds, realElapseSeconds); ProcessWaitingTasks(elapseSeconds, realElapseSeconds); } /// /// 关闭并清理任务池。 /// public void Shutdown() { RemoveAllTasks(); while (FreeAgentCount > 0) { m_FreeAgents.Pop().Shutdown(); } } /// /// 增加任务代理。 /// /// 要增加的任务代理。 public void AddAgent(ITaskAgent agent) { if (agent == null) { throw new GameFrameworkException("Task agent is invalid."); } agent.Initialize(); m_FreeAgents.Push(agent); } /// /// 根据任务的序列编号获取任务的信息。 /// /// 要获取信息的任务的序列编号。 /// 任务的信息。 public TaskInfo GetTaskInfo(int serialId) { foreach (ITaskAgent workingAgent in m_WorkingAgents) { T workingTask = workingAgent.Task; if (workingTask.SerialId == serialId) { return new TaskInfo(workingTask.SerialId, workingTask.Tag, workingTask.Priority, workingTask.UserData, workingTask.Done ? TaskStatus.Done : TaskStatus.Doing, workingTask.Description); } } foreach (T waitingTask in m_WaitingTasks) { if (waitingTask.SerialId == serialId) { return new TaskInfo(waitingTask.SerialId, waitingTask.Tag, waitingTask.Priority, waitingTask.UserData, TaskStatus.Todo, waitingTask.Description); } } return default(TaskInfo); } /// /// 根据任务的标签获取任务的信息。 /// /// 要获取信息的任务的标签。 /// 任务的信息。 public TaskInfo[] GetTaskInfos(string tag) { List results = new List(); GetTaskInfos(tag, results); return results.ToArray(); } /// /// 根据任务的标签获取任务的信息。 /// /// 要获取信息的任务的标签。 /// 任务的信息。 public void GetTaskInfos(string tag, List results) { if (results == null) { throw new GameFrameworkException("Results is invalid."); } results.Clear(); foreach (ITaskAgent workingAgent in m_WorkingAgents) { T workingTask = workingAgent.Task; if (workingTask.Tag == tag) { results.Add(new TaskInfo(workingTask.SerialId, workingTask.Tag, workingTask.Priority, workingTask.UserData, workingTask.Done ? TaskStatus.Done : TaskStatus.Doing, workingTask.Description)); } } foreach (T waitingTask in m_WaitingTasks) { if (waitingTask.Tag == tag) { results.Add(new TaskInfo(waitingTask.SerialId, waitingTask.Tag, waitingTask.Priority, waitingTask.UserData, TaskStatus.Todo, waitingTask.Description)); } } } /// /// 获取所有任务的信息。 /// /// 所有任务的信息。 public TaskInfo[] GetAllTaskInfos() { int index = 0; TaskInfo[] results = new TaskInfo[m_WorkingAgents.Count + m_WaitingTasks.Count]; foreach (ITaskAgent workingAgent in m_WorkingAgents) { T workingTask = workingAgent.Task; results[index++] = new TaskInfo(workingTask.SerialId, workingTask.Tag, workingTask.Priority, workingTask.UserData, workingTask.Done ? TaskStatus.Done : TaskStatus.Doing, workingTask.Description); } foreach (T waitingTask in m_WaitingTasks) { results[index++] = new TaskInfo(waitingTask.SerialId, waitingTask.Tag, waitingTask.Priority, waitingTask.UserData, TaskStatus.Todo, waitingTask.Description); } return results; } /// /// 获取所有任务的信息。 /// /// 所有任务的信息。 public void GetAllTaskInfos(List results) { if (results == null) { throw new GameFrameworkException("Results is invalid."); } results.Clear(); foreach (ITaskAgent workingAgent in m_WorkingAgents) { T workingTask = workingAgent.Task; results.Add(new TaskInfo(workingTask.SerialId, workingTask.Tag, workingTask.Priority, workingTask.UserData, workingTask.Done ? TaskStatus.Done : TaskStatus.Doing, workingTask.Description)); } foreach (T waitingTask in m_WaitingTasks) { results.Add(new TaskInfo(waitingTask.SerialId, waitingTask.Tag, waitingTask.Priority, waitingTask.UserData, TaskStatus.Todo, waitingTask.Description)); } } /// /// 增加任务。 /// /// 要增加的任务。 public void AddTask(T task) { LinkedListNode 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); } } /// /// 根据任务的序列编号移除任务。 /// /// 要移除任务的序列编号。 /// 是否移除任务成功。 public bool RemoveTask(int serialId) { foreach (T task in m_WaitingTasks) { if (task.SerialId == serialId) { m_WaitingTasks.Remove(task); ReferencePool.Release(task); return true; } } LinkedListNode> currentWorkingAgent = m_WorkingAgents.First; while (currentWorkingAgent != null) { LinkedListNode> next = currentWorkingAgent.Next; ITaskAgent workingAgent = currentWorkingAgent.Value; T task = workingAgent.Task; if (task.SerialId == serialId) { workingAgent.Reset(); m_FreeAgents.Push(workingAgent); m_WorkingAgents.Remove(currentWorkingAgent); ReferencePool.Release(task); return true; } currentWorkingAgent = next; } return false; } /// /// 根据任务的标签移除任务。 /// /// 要移除任务的标签。 /// 移除任务的数量。 public int RemoveTasks(string tag) { int count = 0; LinkedListNode currentWaitingTask = m_WaitingTasks.First; while (currentWaitingTask != null) { LinkedListNode next = currentWaitingTask.Next; T task = currentWaitingTask.Value; if (task.Tag == tag) { m_WaitingTasks.Remove(currentWaitingTask); ReferencePool.Release(task); count++; } currentWaitingTask = next; } LinkedListNode> currentWorkingAgent = m_WorkingAgents.First; while (currentWorkingAgent != null) { LinkedListNode> next = currentWorkingAgent.Next; ITaskAgent workingAgent = currentWorkingAgent.Value; T task = workingAgent.Task; if (task.Tag == tag) { workingAgent.Reset(); m_FreeAgents.Push(workingAgent); m_WorkingAgents.Remove(currentWorkingAgent); ReferencePool.Release(task); count++; } currentWorkingAgent = next; } return count; } /// /// 移除所有任务。 /// /// 移除任务的数量。 public int RemoveAllTasks() { int count = m_WaitingTasks.Count + m_WorkingAgents.Count; foreach (T task in m_WaitingTasks) { ReferencePool.Release(task); } m_WaitingTasks.Clear(); foreach (ITaskAgent workingAgent in m_WorkingAgents) { T task = workingAgent.Task; workingAgent.Reset(); m_FreeAgents.Push(workingAgent); ReferencePool.Release(task); } m_WorkingAgents.Clear(); return count; } private void ProcessRunningTasks(float elapseSeconds, float realElapseSeconds) { LinkedListNode> 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> next = current.Next; current.Value.Reset(); m_FreeAgents.Push(current.Value); m_WorkingAgents.Remove(current); ReferencePool.Release(task); current = next; } } private void ProcessWaitingTasks(float elapseSeconds, float realElapseSeconds) { LinkedListNode current = m_WaitingTasks.First; while (current != null && FreeAgentCount > 0) { ITaskAgent agent = m_FreeAgents.Pop(); LinkedListNode> agentNode = m_WorkingAgents.AddLast(agent); T task = current.Value; LinkedListNode next = current.Next; StartTaskStatus status = agent.Start(task); if (status == StartTaskStatus.Done || status == StartTaskStatus.HasToWait || status == StartTaskStatus.UnknownError) { agent.Reset(); m_FreeAgents.Push(agent); m_WorkingAgents.Remove(agentNode); } if (status == StartTaskStatus.Done || status == StartTaskStatus.CanResume || status == StartTaskStatus.UnknownError) { m_WaitingTasks.Remove(current); } if (status == StartTaskStatus.Done || status == StartTaskStatus.UnknownError) { ReferencePool.Release(task); } current = next; } } } }