using Convention.Collections;
using Convention.Collections.Generic;
using Convention.ReferenceManagement;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Convention.TaskManagement
{
///
/// 任务基类
///
public abstract class TaskBase: IReference
{
///
/// 任务默认优先级。
///
public const int DefaultPriority = 0;
private int m_SerialId;
private string m_Tag;
private int m_Priority;
private object m_UserData;
private bool m_Done;
///
/// 初始化任务基类的新实例
///
public TaskBase()
{
m_SerialId = 0;
m_Tag = null;
m_Priority = DefaultPriority;
m_Done = false;
m_UserData = null;
}
///
/// 获取任务的序列编号
///
public int SerialId
{
get
{
return m_SerialId;
}
}
///
/// 获取任务的标签
///
public string Tag
{
get
{
return m_Tag;
}
}
///
/// 获取任务的优先级
///
public int Priority
{
get
{
return m_Priority;
}
}
///
/// 获取任务的用户自定义数据
///
public object UserData
{
get
{
return m_UserData;
}
}
///
/// 获取或设置任务是否完成
///
public bool Done
{
get
{
return m_Done;
}
set
{
m_Done = value;
}
}
///
/// 获取任务描述
///
public virtual string Description
{
get
{
return null;
}
}
///
/// 初始化任务基类
///
/// 任务的序列编号
/// 任务的标签
/// 任务的优先级
/// 任务的用户自定义数据
internal void Initialize(int serialId, string tag, int priority, object userData)
{
m_SerialId = serialId;
m_Tag = tag;
m_Priority = priority;
m_UserData = userData;
m_Done = false;
}
///
/// 清理任务基类
///
public virtual void Clear()
{
m_SerialId = 0;
m_Tag = null;
m_Priority = DefaultPriority;
m_UserData = null;
m_Done = false;
}
}
///
/// 开始处理任务的状态
///
public enum StartTaskStatus : byte
{
///
/// 可以立刻处理完成此任务
///
Done = 0,
///
/// 可以继续处理此任务
///
CanResume,
///
/// 不能继续处理此任务,需等待其它任务执行完成
///
HasToWait,
///
/// 不能继续处理此任务,出现未知错误
///
UnknownError
}
///
/// 任务代理接口
///
/// 任务类型
public interface ITaskAgent where T : TaskBase
{
///
/// 获取任务
///
T Task
{
get;
}
///
/// 初始化任务代理
///
void Initialize();
///
/// 任务代理轮询
///
/// 逻辑流逝时间,以秒为单位
/// 真实流逝时间,以秒为单位
void Update(float elapseSeconds, float realElapseSeconds);
///
/// 关闭并清理任务代理
///
void Shutdown();
///
/// 开始处理任务
///
/// 要处理的任务
/// 开始处理任务的状态
StartTaskStatus Start(T task);
///
/// 停止正在处理的任务并重置任务代理
///
void Reset();
}
///
/// 任务状态
///
public enum TaskStatus : byte
{
///
/// 未开始
///
Todo = 0,
///
/// 执行中
///
Doing,
///
/// 完成
///
Done
}
///
/// 任务信息
///
[StructLayout(LayoutKind.Auto)]
public readonly struct TaskInfo
{
private readonly bool m_IsValid;
private readonly int m_SerialId;
private readonly string m_Tag;
private readonly int m_Priority;
private readonly object m_UserData;
private readonly TaskStatus m_Status;
private readonly string m_Description;
///
/// 初始化任务信息的新实例。
///
/// 任务的序列编号
/// 任务的标签
/// 任务的优先级
/// 任务的用户自定义数据
/// 任务状态
/// 任务描述
public TaskInfo(int serialId, string tag, int priority, object userData, TaskStatus status, string description)
{
m_IsValid = true;
m_SerialId = serialId;
m_Tag = tag;
m_Priority = priority;
m_UserData = userData;
m_Status = status;
m_Description = description;
}
///
/// 获取任务信息是否有效
///
public bool IsValid
{
get
{
return m_IsValid;
}
}
///
/// 获取任务的序列编号
///
public int SerialId
{
get
{
if (!m_IsValid)
{
throw new InvalidOperationException("Data is invalid.");
}
return m_SerialId;
}
}
///
/// 获取任务的标签
///
public string Tag
{
get
{
if (!m_IsValid)
{
throw new InvalidOperationException("Data is invalid.");
}
return m_Tag;
}
}
///
/// 获取任务的优先级
///
public int Priority
{
get
{
if (!m_IsValid)
{
throw new InvalidOperationException("Data is invalid.");
}
return m_Priority;
}
}
///
/// 获取任务的用户自定义数据
///
public object UserData
{
get
{
if (!m_IsValid)
{
throw new InvalidOperationException("Data is invalid.");
}
return m_UserData;
}
}
///
/// 获取任务状态
///
public TaskStatus Status
{
get
{
if (!m_IsValid)
{
throw new InvalidOperationException("Data is invalid.");
}
return m_Status;
}
}
///
/// 获取任务描述
///
public string Description
{
get
{
if (!m_IsValid)
{
throw new InvalidOperationException("Data is invalid.");
}
return m_Description;
}
}
}
///
/// 任务池
///
/// 任务类型
public class TaskPool where T : TaskBase
{
private readonly Stack> m_FreeAgents;
private readonly LinkedCacheList> m_WorkingAgents;
private readonly LinkedCacheList m_WaitingTasks;
private bool m_Paused;
///
/// 初始化任务池的新实例。
///
public TaskPool()
{
m_FreeAgents = new Stack>();
m_WorkingAgents = new LinkedCacheList>();
m_WaitingTasks = new LinkedCacheList();
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 InvalidOperationException("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 InvalidOperationException("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 InvalidOperationException("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;
}
}
}
}