Files
YooAssetScene/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs
T
2026-01-17 18:44:48 +08:00

269 lines
7.9 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace YooAsset
{
internal static class OperationSystem
{
#if UNITY_EDITOR
[UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.SubsystemRegistration)]
private static void OnRuntimeInitialize()
{
DestroyAll();
}
#endif
public const string GlobalSchedulerName = "YOOASSET_GLOBAL_SCHEDULER"; // 全局调度器名称
private const long MinTimeSlice = 10; // 最小时间片(毫秒)
private static readonly Dictionary<string, OperationScheduler> _schedulerDic = new Dictionary<string, OperationScheduler>(100);
private static readonly List<OperationScheduler> _schedulerList = new List<OperationScheduler>(100);
private static bool _isInitialized;
private static int _createIndex;
// 计时器相关
private static Stopwatch _watch;
private static long _frameTime;
private static long _maxTimeSlice = long.MaxValue;
/// <summary>
/// 异步操作系统的每帧最大执行预算(毫秒)
/// </summary>
public static long MaxTimeSlice
{
get
{
return _maxTimeSlice;
}
set
{
if (value < MinTimeSlice)
{
_maxTimeSlice = MinTimeSlice;
YooLogger.Warning($"MaxTimeSlice minimum value is {MinTimeSlice} milliseconds.");
}
else
{
_maxTimeSlice = value;
}
}
}
/// <summary>
/// 异步操作系统是否繁忙
/// </summary>
public static bool IsBusy
{
get
{
if (_watch == null)
return false;
if (_maxTimeSlice == long.MaxValue)
return false;
// 注意 : 单次调用开销约1微秒
return _watch.ElapsedMilliseconds - _frameTime >= _maxTimeSlice;
}
}
/// <summary>
/// 初始化异步操作系统
/// </summary>
public static void Initialize()
{
if (_isInitialized)
{
YooLogger.Warning("Operation system is already initialized.");
return;
}
_isInitialized = true;
_watch = Stopwatch.StartNew();
// 创建全局调度器
CreatePackageScheduler(GlobalSchedulerName, uint.MaxValue);
}
/// <summary>
/// 更新异步操作系统
/// </summary>
public static void Update()
{
if (_isInitialized == false)
return;
// 检测是否需要执行排序
bool isDirty = false;
foreach (var scheduler in _schedulerList)
{
if (scheduler.IsDirty)
{
scheduler.IsDirty = false;
isDirty = true;
}
}
if (isDirty)
{
_schedulerList.Sort();
}
// 更新帧时间
_frameTime = _watch.ElapsedMilliseconds;
// 更新调度器
for (int i = 0; i < _schedulerList.Count; i++)
{
if (IsBusy)
break;
_schedulerList[i].Update();
}
}
/// <summary>
/// 销毁异步操作系统
/// </summary>
public static void DestroyAll()
{
_isInitialized = false;
// 清空所有调度器
foreach (var scheduler in _schedulerList)
{
scheduler.ClearAll();
}
_schedulerDic.Clear();
_schedulerList.Clear();
_createIndex = 0;
_watch = null;
_frameTime = 0;
_maxTimeSlice = long.MaxValue;
}
/// <summary>
/// 创建包裹调度器
/// </summary>
public static OperationScheduler CreatePackageScheduler(string packageName, uint priority)
{
DebugEnsureInitialized(packageName);
if (_schedulerDic.ContainsKey(packageName))
{
throw new YooInternalException($"Package scheduler already exists: {packageName}");
}
var scheduler = new OperationScheduler(packageName, _createIndex++);
_schedulerDic.Add(packageName, scheduler);
_schedulerList.Add(scheduler);
scheduler.Priority = priority;
return scheduler;
}
/// <summary>
/// 销毁包裹调度器
/// </summary>
public static void DestroyPackageScheduler(string packageName)
{
DebugEnsureInitialized(packageName);
// 不允许销毁默认调度器
if (packageName == GlobalSchedulerName)
{
throw new YooInternalException("Cannot destroy the global package scheduler.");
}
if (_schedulerDic.TryGetValue(packageName, out var scheduler))
{
scheduler.ClearAll();
_schedulerDic.Remove(packageName);
_schedulerList.Remove(scheduler);
}
}
/// <summary>
/// 销毁包裹的所有任务
/// </summary>
public static void ClearPackageOperation(string packageName)
{
DebugEnsureInitialized(packageName);
var scheduler = GetScheduler(packageName);
scheduler.ClearAll();
}
/// <summary>
/// 开始处理异步操作类
/// </summary>
public static void StartOperation(string packageName, AsyncOperationBase operation)
{
DebugEnsureInitialized(packageName);
var scheduler = GetScheduler(packageName);
scheduler.StartOperation(operation);
}
/// <summary>
/// 设置调度器优先级
/// </summary>
public static void SetSchedulerPriority(string packageName, uint priority)
{
DebugEnsureInitialized(packageName);
var scheduler = GetScheduler(packageName);
scheduler.Priority = priority;
}
/// <summary>
/// 获取调度器优先级
/// </summary>
public static uint GetSchedulerPriority(string packageName)
{
DebugEnsureInitialized(packageName);
var scheduler = GetScheduler(packageName);
return scheduler.Priority;
}
/// <summary>
/// 获取调度器(严格模式)
/// </summary>
private static OperationScheduler GetScheduler(string packageName)
{
if (_schedulerDic.TryGetValue(packageName, out var scheduler))
{
return scheduler;
}
// 严格模式:非默认包裹必须先创建调度器
throw new YooInternalException($"Operation scheduler not found: {packageName}.");
}
#region 调试信息
internal static List<DebugOperationInfo> GetDebugOperationInfos(string packageName)
{
DebugEnsureInitialized(packageName);
var scheduler = GetScheduler(packageName);
return scheduler.GetDebugOperationInfos();
}
#endregion
#region 调试方法
[Conditional("DEBUG")]
private static void DebugEnsureInitialized(string packageName)
{
if (string.IsNullOrWhiteSpace(packageName))
throw new YooInternalException("Package name is null or empty.");
if (_isInitialized == false)
throw new YooInternalException($"{nameof(OperationSystem)} not initialized.");
}
#endregion
}
}