62 lines
2.0 KiB
C#
62 lines
2.0 KiB
C#
#nullable enable
|
|
using System;
|
|
using Cysharp.Threading.Tasks;
|
|
|
|
namespace ShrinkContext
|
|
{
|
|
/// <summary>
|
|
/// 单个可逆效应的句柄(论文算法 1 的 effect 封装)。
|
|
/// 前向执行时产出逆操作并累积在句柄内部;DisposeAsync 至多执行一次(armed 语义),
|
|
/// 若前向仍在进行中则先等待其完成再运行累积的逆操作(dispose = await task; recover())。
|
|
/// </summary>
|
|
public sealed class ShrinkEffectHandle
|
|
{
|
|
private static readonly Func<UniTask> Nop = static () => UniTask.CompletedTask;
|
|
|
|
private bool _armed = true;
|
|
private UniTask _forwardTask;
|
|
private bool _hasForwardTask;
|
|
private Func<UniTask> _inverseChain = Nop;
|
|
|
|
public bool IsArmed => _armed;
|
|
|
|
/// <summary>登记一个进行中的异步前向;DisposeAsync 会先等待它完成。</summary>
|
|
internal void BeginForward(UniTask forwardTask)
|
|
{
|
|
_forwardTask = forwardTask;
|
|
_hasForwardTask = true;
|
|
}
|
|
|
|
/// <summary>前向完成后登记其逆操作;新逆操作在链首执行(LIFO)。</summary>
|
|
internal void CompleteForward(Func<UniTask> inverse)
|
|
{
|
|
if (inverse == null)
|
|
return;
|
|
|
|
var previous = _inverseChain;
|
|
_inverseChain = async () =>
|
|
{
|
|
await inverse();
|
|
await previous();
|
|
};
|
|
}
|
|
|
|
/// <summary>直接附加逆操作(等效于前向已同步完成)。</summary>
|
|
internal void AttachInverse(Func<UniTask> inverse) => CompleteForward(inverse);
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
if (!_armed)
|
|
return;
|
|
|
|
_armed = false;
|
|
if (_hasForwardTask && _forwardTask.Status == UniTaskStatus.Pending)
|
|
await _forwardTask;
|
|
|
|
var chain = _inverseChain;
|
|
_inverseChain = Nop;
|
|
await chain();
|
|
}
|
|
}
|
|
}
|