using GFramework.Core.Abstractions.lifecycle;
using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.pause;
using GFramework.Core.logging;
using GFramework.Core.utility;
namespace GFramework.Core.pause;
///
/// 暂停栈管理器实现,用于管理游戏中的暂停状态。
/// 支持多组暂停、嵌套暂停、以及暂停状态的通知机制。
///
public class PauseStackManager : AbstractContextUtility, IPauseStackManager, IAsyncDestroyable
{
private readonly List _handlers = new();
private readonly ReaderWriterLockSlim _lock = new();
private readonly ILogger _logger = LoggerFactoryResolver.Provider.CreateLogger(nameof(PauseStackManager));
private readonly Dictionary> _pauseStacks = new();
private readonly Dictionary _tokenMap = new();
///
/// 异步销毁方法,在组件销毁时调用。
///
/// 表示异步操作完成的任务。
public ValueTask DestroyAsync()
{
_lock.Dispose();
return ValueTask.CompletedTask;
}
///
/// 暂停状态变化事件,当暂停状态发生改变时触发。
///
public event Action? OnPauseStateChanged;
///
/// 推入一个新的暂停请求到指定的暂停组中。
///
/// 暂停的原因描述。
/// 暂停组,默认为全局暂停组。
/// 表示此次暂停请求的令牌。
public PauseToken Push(string reason, PauseGroup group = PauseGroup.Global)
{
_lock.EnterWriteLock();
try
{
var wasPaused = IsPausedInternal(group);
var entry = new PauseEntry
{
TokenId = Guid.NewGuid(),
Reason = reason,
Group = group,
Timestamp = DateTime.UtcNow
};
if (!_pauseStacks.TryGetValue(group, out var stack))
{
stack = new Stack();
_pauseStacks[group] = stack;
}
stack.Push(entry);
_tokenMap[entry.TokenId] = entry;
_logger.Debug($"Pause pushed: {reason} (Group: {group}, Depth: {stack.Count})");
// 状态变化检测:从未暂停 → 暂停
if (!wasPaused)
{
NotifyHandlers(group, true);
}
return new PauseToken(entry.TokenId);
}
finally
{
_lock.ExitWriteLock();
}
}
///
/// 弹出指定的暂停请求。
///
/// 要弹出的暂停令牌。
/// 如果成功弹出则返回true,否则返回false。
public bool Pop(PauseToken token)
{
if (!token.IsValid)
return false;
_lock.EnterWriteLock();
try
{
if (!_tokenMap.TryGetValue(token.Id, out var entry))
{
_logger.Warn($"Attempted to pop invalid/expired token: {token.Id}");
return false;
}
var group = entry.Group;
var stack = _pauseStacks[group];
var wasPaused = stack.Count > 0;
// 从栈中移除
var tempStack = new Stack();
bool found = false;
while (stack.Count > 0)
{
var current = stack.Pop();
if (current.TokenId == token.Id)
{
found = true;
break;
}
tempStack.Push(current);
}
// 恢复栈结构
while (tempStack.Count > 0)
{
stack.Push(tempStack.Pop());
}
if (found)
{
_tokenMap.Remove(token.Id);
_logger.Debug($"Pause popped: {entry.Reason} (Group: {group}, Remaining: {stack.Count})");
// 状态变化检测:从暂停 → 未暂停
if (wasPaused && stack.Count == 0)
{
NotifyHandlers(group, false);
}
}
return found;
}
finally
{
_lock.ExitWriteLock();
}
}
///
/// 查询指定暂停组当前是否处于暂停状态。
///
/// 要查询的暂停组,默认为全局暂停组。
/// 如果该组处于暂停状态则返回true,否则返回false。
public bool IsPaused(PauseGroup group = PauseGroup.Global)
{
_lock.EnterReadLock();
try
{
return IsPausedInternal(group);
}
finally
{
_lock.ExitReadLock();
}
}
///
/// 获取指定暂停组的暂停深度(即嵌套暂停的层数)。
///
/// 要查询的暂停组,默认为全局暂停组。
/// 暂停深度,0表示未暂停。
public int GetPauseDepth(PauseGroup group = PauseGroup.Global)
{
_lock.EnterReadLock();
try
{
return _pauseStacks.TryGetValue(group, out var stack) ? stack.Count : 0;
}
finally
{
_lock.ExitReadLock();
}
}
///
/// 获取指定暂停组的所有暂停原因。
///
/// 要查询的暂停组,默认为全局暂停组。
/// 包含所有暂停原因的只读列表。
public IReadOnlyList GetPauseReasons(PauseGroup group = PauseGroup.Global)
{
_lock.EnterReadLock();
try
{
if (!_pauseStacks.TryGetValue(group, out var stack))
return Array.Empty();
return stack.Select(e => e.Reason).ToList();
}
finally
{
_lock.ExitReadLock();
}
}
///
/// 创建一个暂停作用域,支持 using 语法自动管理暂停生命周期。
///
/// 暂停的原因描述。
/// 暂停组,默认为全局暂停组。
/// 表示暂停作用域的 IDisposable 对象。
public IDisposable PauseScope(string reason, PauseGroup group = PauseGroup.Global)
{
return new PauseScope(this, reason, group);
}
///
/// 清空指定暂停组的所有暂停请求。
///
/// 要清空的暂停组。
public void ClearGroup(PauseGroup group)
{
_lock.EnterWriteLock();
try
{
if (!_pauseStacks.TryGetValue(group, out var stack))
return;
var wasPaused = stack.Count > 0;
// 移除所有令牌
foreach (var entry in stack)
{
_tokenMap.Remove(entry.TokenId);
}
stack.Clear();
_logger.Warn($"Cleared all pauses for group: {group}");
// 状态变化检测
if (wasPaused)
{
NotifyHandlers(group, false);
}
}
finally
{
_lock.ExitWriteLock();
}
}
///
/// 清空所有暂停组的所有暂停请求。
///
public void ClearAll()
{
_lock.EnterWriteLock();
try
{
var pausedGroups = _pauseStacks
.Where(kvp => kvp.Value.Count > 0)
.Select(kvp => kvp.Key)
.ToList();
_pauseStacks.Clear();
_tokenMap.Clear();
_logger.Warn("Cleared all pauses for all groups");
// 通知所有之前暂停的组
foreach (var group in pausedGroups)
{
NotifyHandlers(group, false);
}
}
finally
{
_lock.ExitWriteLock();
}
}
///
/// 注册一个暂停处理器,用于监听暂停状态的变化。
///
/// 要注册的暂停处理器。
public void RegisterHandler(IPauseHandler handler)
{
_lock.EnterWriteLock();
try
{
if (!_handlers.Contains(handler))
{
_handlers.Add(handler);
_logger.Debug($"Registered pause handler: {handler.GetType().Name}");
}
}
finally
{
_lock.ExitWriteLock();
}
}
///
/// 注销一个已注册的暂停处理器。
///
/// 要注销的暂停处理器。
public void UnregisterHandler(IPauseHandler handler)
{
_lock.EnterWriteLock();
try
{
if (_handlers.Remove(handler))
{
_logger.Debug($"Unregistered pause handler: {handler.GetType().Name}");
}
}
finally
{
_lock.ExitWriteLock();
}
}
///
/// 内部查询暂停状态的方法,不加锁。
///
/// 要查询的暂停组。
/// 如果该组处于暂停状态则返回true,否则返回false。
private bool IsPausedInternal(PauseGroup group)
{
return _pauseStacks.TryGetValue(group, out var stack) && stack.Count > 0;
}
///
/// 通知所有已注册的处理器和事件订阅者暂停状态的变化。
///
/// 发生状态变化的暂停组。
/// 新的暂停状态。
private void NotifyHandlers(PauseGroup group, bool isPaused)
{
_logger.Debug($"Notifying handlers: Group={group}, IsPaused={isPaused}");
// 按优先级排序后通知
foreach (var handler in _handlers.OrderBy(h => h.Priority))
{
try
{
handler.OnPauseStateChanged(group, isPaused);
}
catch (Exception ex)
{
_logger.Error($"Handler {handler.GetType().Name} failed", ex);
}
}
// 触发事件
OnPauseStateChanged?.Invoke(group, isPaused);
}
///
/// 初始化方法,在组件初始化时调用。
///
protected override void OnInit()
{
}
}