Files
cneicy 6eebb8e8e4
Publish UPM package / publish (push) Failing after 1s
chore: initialize standalone UPM package
2026-08-26 02:49:58 +08:00

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();
}
}
}