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