Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 80 additions & 117 deletions GFramework.Core/state/StateMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ namespace GFramework.Core.state;
public class StateMachine(int maxHistorySize = 10) : IStateMachine
{
private readonly object _lock = new();
private readonly HashSet<IState> _registeredStates = new(); // 优化:用于快速检查状态是否注册

private readonly HashSet<IState> _registeredStates = [];
private readonly Stack<IState> _stateHistory = new();
private readonly SemaphoreSlim _transitionLock = new(1, 1);

/// <summary>
/// 存储所有已注册状态的字典,键为状态类型,值为状态实例
Expand Down Expand Up @@ -43,18 +45,7 @@ public IStateMachine Register(IState state)
/// <typeparam name="T">要注销的状态类型</typeparam>
public IStateMachine Unregister<T>() where T : IState
{
var stateToUnregister = PrepareUnregister<T>(out var isCurrentState);
if (stateToUnregister == null) return this;

// 如果是当前状态,执行同步退出
if (isCurrentState)
{
Current!.OnExit(null);
Current = null;
}

CompleteUnregister(stateToUnregister);
return this;
return UnregisterAsync<T>().GetAwaiter().GetResult();
}

/// <summary>
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
Outdated
Expand All @@ -63,31 +54,36 @@ public IStateMachine Unregister<T>() where T : IState
/// <typeparam name="T">要注销的状态类型</typeparam>
public async Task<IStateMachine> UnregisterAsync<T>() where T : IState
{
var stateToUnregister = PrepareUnregister<T>(out var isCurrentState);
if (stateToUnregister == null) return this;
await _transitionLock.WaitAsync();
try
{
var stateToUnregister = PrepareUnregister<T>(out var isCurrentState);
if (stateToUnregister == null) return this;

// 如果是当前状态,执行异步退出
if (isCurrentState)
if (isCurrentState)
{
await ExecuteExitAsync(Current!, null);
Current = null;
}

CompleteUnregister(stateToUnregister);
return this;
}
finally
{
await ExecuteExitAsync(Current!, null);
Current = null;
_transitionLock.Release();
}

CompleteUnregister(stateToUnregister);
return this;
}


/// <summary>
/// 检查是否可以切换到指定类型的状态
/// </summary>
/// <typeparam name="T">目标状态类型</typeparam>
/// <returns>如果可以切换则返回true,否则返回false</returns>
public bool CanChangeTo<T>() where T : IState
{
if (!States.TryGetValue(typeof(T), out var target))
return false;

return Current?.CanTransitionTo(target) ?? true;
return CanChangeToAsync<T>().GetAwaiter().GetResult();
}

/// <summary>
Expand All @@ -97,14 +93,23 @@ public bool CanChangeTo<T>() where T : IState
/// <returns>如果可以切换则返回true,否则返回false</returns>
public async Task<bool> CanChangeToAsync<T>() where T : IState
{
if (!States.TryGetValue(typeof(T), out var target))
return false;
await _transitionLock.WaitAsync();
try
{
if (!States.TryGetValue(typeof(T), out var target))
return false;

if (Current == null) return true;
if (Current == null) return true;

return await CanTransitionToAsync(Current, target);
return await CanTransitionToAsync(Current, target);
}
finally
{
_transitionLock.Release();
}
}


/// <summary>
/// 切换到指定类型的状态
/// </summary>
Expand All @@ -113,22 +118,10 @@ public async Task<bool> CanChangeToAsync<T>() where T : IState
/// <exception cref="InvalidOperationException">当目标状态未注册时抛出</exception>
public bool ChangeTo<T>() where T : IState
{
lock (_lock)
{
if (!States.TryGetValue(typeof(T), out var target))
throw new InvalidOperationException($"State {typeof(T).Name} not registered.");

if (Current != null && !Current.CanTransitionTo(target))
{
OnTransitionRejected(Current, target);
return false;
}

ChangeInternal(target);
return true;
}
return ChangeToAsync<T>().GetAwaiter().GetResult();
}


/// <summary>
/// 异步切换到指定类型的状态
/// </summary>
Expand All @@ -137,30 +130,37 @@ public bool ChangeTo<T>() where T : IState
/// <exception cref="InvalidOperationException">当目标状态未注册时抛出</exception>
public async Task<bool> ChangeToAsync<T>() where T : IState
{
IState target;
IState? currentSnapshot;

lock (_lock)
await _transitionLock.WaitAsync();
try
{
if (!States.TryGetValue(typeof(T), out target!))
throw new InvalidOperationException($"State {typeof(T).Name} not registered.");
IState target;
IState? currentSnapshot;

currentSnapshot = Current; // 在锁内获取当前状态的快照
}
lock (_lock)
{
if (!States.TryGetValue(typeof(T), out target!))
throw new InvalidOperationException($"State {typeof(T).Name} not registered.");

// 验证转换(在锁外执行异步操作)
if (currentSnapshot != null)
{
var canTransition = await CanTransitionToAsync(currentSnapshot, target);
if (!canTransition)
currentSnapshot = Current;
}

if (currentSnapshot != null)
{
await OnTransitionRejectedAsync(currentSnapshot, target);
return false;
var canTransition = await CanTransitionToAsync(currentSnapshot, target);
if (!canTransition)
{
await OnTransitionRejectedAsync(currentSnapshot, target);
return false;
}
}
}

await ChangeInternalAsync(target);
return true;
await ChangeInternalAsync(target);
return true;
}
finally
{
_transitionLock.Release();
}
}

/// <summary>
Expand Down Expand Up @@ -222,11 +222,7 @@ public IReadOnlyList<IState> GetStateHistory()
/// <returns>如果成功回退则返回true,否则返回false</returns>
public bool GoBack()
{
var previousState = FindValidPreviousState();
if (previousState == null) return false;

ChangeInternalWithoutHistory(previousState);
return true;
return GoBackAsync().GetAwaiter().GetResult();
}

/// <summary>
Expand All @@ -235,11 +231,19 @@ public bool GoBack()
/// <returns>如果成功回退则返回true,否则返回false</returns>
public async Task<bool> GoBackAsync()
{
var previousState = FindValidPreviousState();
if (previousState == null) return false;
await _transitionLock.WaitAsync();
try
{
var previousState = FindValidPreviousState();
if (previousState == null) return false;

await ChangeInternalWithoutHistoryAsync(previousState);
return true;
await ChangeInternalWithoutHistoryAsync(previousState);
return true;
}
finally
{
_transitionLock.Release();
}
}

/// <summary>
Expand Down Expand Up @@ -310,24 +314,6 @@ private void CompleteUnregister(IState stateToUnregister)
}
}

/// <summary>
/// 内部状态切换方法(不记录历史),用于回退操作
/// </summary>
/// <param name="next">下一个状态实例</param>
protected virtual void ChangeInternalWithoutHistory(IState next)
{
if (Current == next) return;

var old = Current;
OnStateChanging(old, next);

old?.OnExit(next);
Current = next;
Current.OnEnter(old);

OnStateChanged(old, Current);
}

/// <summary>
/// 异步内部状态切换方法(不记录历史),用于回退操作
/// </summary>
Expand All @@ -346,32 +332,6 @@ protected virtual async Task ChangeInternalWithoutHistoryAsync(IState next)
await OnStateChangedAsync(old, Current);
}

/// <summary>
/// 内部状态切换方法,处理状态切换的核心逻辑
/// </summary>
/// <param name="next">下一个状态实例</param>
protected virtual void ChangeInternal(IState next)
{
if (Current == next) return;

if (Current != null && !Current.CanTransitionTo(next))
{
OnTransitionRejected(Current, next);
return;
}

var old = Current;
OnStateChanging(old, next);

AddToHistory(Current);

old?.OnExit(next);
Current = next;
Current.OnEnter(old);

OnStateChanged(old, Current);
}

/// <summary>
/// 异步内部状态切换方法,处理状态切换的核心逻辑
/// </summary>
Expand All @@ -383,12 +343,15 @@ protected virtual async Task ChangeInternalAsync(IState next)
var old = Current;
await OnStateChangingAsync(old, next);

AddToHistory(Current);

await ExecuteExitAsync(old, next);

AddToHistory(old);

Current = next;

await ExecuteEnterAsync(Current, old);


await OnStateChangedAsync(old, Current);
}

Expand Down
16 changes: 0 additions & 16 deletions GFramework.Core/state/StateMachineSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,6 @@ public virtual void Destroy()
States.Clear();
}

/// <summary>
/// 内部状态切换方法,重写基类方法以添加状态变更事件通知功能
/// </summary>
/// <param name="next">要切换到的下一个状态</param>
protected override void ChangeInternal(IState next)
{
var old = Current;
base.ChangeInternal(next);

// 发送状态变更事件,通知监听者状态已发生改变
this.SendEvent(new StateChangedEvent
{
OldState = old,
NewState = Current
});
}

/// <summary>
/// 异步内部状态切换方法,重写基类方法以添加状态变更事件通知功能
Expand Down
Loading