using System.Collections;
using GFramework.Game.Abstractions.coroutine;
namespace GFramework.Game.coroutine;
///
/// 协程作用域管理器,用于管理和控制协程的生命周期
///
public sealed class CoroutineScope : ICoroutineScope, IDisposable
{
private readonly List _children = new();
private readonly HashSet _runningCoroutines = new();
private readonly CoroutineScheduler _scheduler;
private bool _isActive = true;
///
/// 初始化新的协程作用域实例
///
/// 协程调度器
/// 作用域名称,如果为null则自动生成
/// 父级作用域,如果为null则表示顶级作用域
public CoroutineScope(CoroutineScheduler scheduler, string? name = null, CoroutineScope? parent = null)
{
_scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler));
parent?._children.Add(this);
Name = name ?? $"Scope_{GetHashCode()}";
}
///
/// 获取作用域名称
///
public string Name { get; }
///
/// 获取当前作用域是否处于活动状态
///
public bool IsActive => _isActive;
///
/// 取消当前作用域及其所有子作用域中的所有运行中协程
///
public void Cancel()
{
if (!_isActive) return;
_isActive = false;
// 递归取消所有子作用域
foreach (var child in _children)
child.Cancel();
// 取消当前作用域中所有运行中的协程
foreach (var handle in _runningCoroutines)
handle.Cancel();
_runningCoroutines.Clear();
}
///
/// 启动一个新的协程(接口实现)
///
/// 要执行的协程枚举器
/// 协程句柄
ICoroutineHandle ICoroutineScope.Launch(IEnumerator routine)
{
return Launch(routine);
}
///
/// 释放资源并取消所有协程
///
public void Dispose() => Cancel();
///
/// 启动一个新的协程
///
/// 要执行的协程枚举器
/// 协程句柄
public CoroutineHandle Launch(IEnumerator routine)
{
if (!_isActive)
throw new InvalidOperationException($"Scope '{Name}' is not active");
var context = new CoroutineContext(this, _scheduler, this);
var handle = _scheduler.StartCoroutine(routine, context);
// 添加到运行中协程集合
_runningCoroutines.Add(handle);
// 注册完成事件以从集合中移除句柄
handle.OnComplete += () => _runningCoroutines.Remove(handle);
// 注册错误事件以从集合中移除句柄
handle.OnError += (_) => _runningCoroutines.Remove(handle);
return handle;
}
}