Files
YooAsset/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs
2026-01-20 19:20:50 +08:00

273 lines
8.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace YooAsset
{
/// <summary>
/// 异步操作系统(静态调度器)
/// 负责管理所有包裹的调度器,提供时间切片执行机制
/// </summary>
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> _schedulerDict = new Dictionary<string, OperationScheduler>(100);
private static readonly List<OperationScheduler> _schedulerList = new List<OperationScheduler>(100);
private static bool _isInitialized;
private static int _nextCreationIndex;
// 计时器相关
private static Stopwatch _systemStopwatch;
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 (_systemStopwatch == null)
return false;
if (_maxTimeSlice == long.MaxValue)
return false;
// 注意 : 单次调用开销约1微秒
return _systemStopwatch.ElapsedMilliseconds - _frameTime >= _maxTimeSlice;
}
}
/// <summary>
/// 初始化异步操作系统
/// </summary>
public static void Initialize()
{
if (_isInitialized)
{
YooLogger.Warning("Operation system is already initialized.");
return;
}
_isInitialized = true;
_systemStopwatch = 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 = _systemStopwatch.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();
}
_schedulerDict.Clear();
_schedulerList.Clear();
_nextCreationIndex = 0;
_systemStopwatch = null;
_frameTime = 0;
_maxTimeSlice = long.MaxValue;
}
/// <summary>
/// 创建包裹调度器
/// </summary>
public static OperationScheduler CreatePackageScheduler(string packageName, uint priority)
{
DebugEnsureInitialized(packageName);
if (_schedulerDict.ContainsKey(packageName))
{
throw new YooInternalException($"Package scheduler already exists: {packageName}");
}
var scheduler = new OperationScheduler(packageName, _nextCreationIndex++);
_schedulerDict.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 (_schedulerDict.TryGetValue(packageName, out var scheduler))
{
scheduler.ClearAll();
_schedulerDict.Remove(packageName);
_schedulerList.Remove(scheduler);
}
}
/// <summary>
/// 销毁包裹的所有任务
/// </summary>
public static void ClearPackageOperations(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 (_schedulerDict.TryGetValue(packageName, out var scheduler))
{
return scheduler;
}
// 严格模式:非默认包裹必须先创建调度器
throw new YooInternalException($"Operation scheduler not found: {packageName}.");
}
#region
internal static List<DiagnosticOperationInfo> 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
}
}