using System;
using System.Collections.Generic;
#if DOTCRAFT_ATTACH
namespace DotCraft.Unity
#else
namespace DotCraft.Editor
#endif
{
/// Advances snippet continuations on the owner's Unity main-thread pump.
public sealed class UnityContinuationScheduler
{
readonly List pending = new List();
readonly Func clock;
long tick;
public UnityContinuationScheduler(Func clock) { this.clock = clock ?? throw new ArgumentNullException(nameof(clock)); }
/// Schedules a continuation; callers must serialize access on Unity's main thread.
public void Schedule(UnityExecutionContext context, Action continuation, int frames, double seconds, Func predicate)
{
pending.Add(new Continuation { Context = context, Action = continuation,
Tick = tick + Math.Max(1, frames), Time = clock() + Math.Max(0, seconds), Predicate = predicate });
}
public void Pump()
{
tick++;
var now = clock();
var snapshot = pending.ToArray();
foreach (var item in snapshot)
{
if (!item.Context.IsCancellationRequested
&& (tick < item.Tick || now < item.Time || !item.Context.Evaluate(item.Predicate))) continue;
pending.Remove(item);
item.Action();
}
}
/// Invalidates and resumes pending awaits before the domain is unloaded.
public void Invalidate()
{
var snapshot = pending.ToArray();
pending.Clear();
foreach (var item in snapshot) item.Context.Invalidate();
foreach (var item in snapshot) item.Action();
}
sealed class Continuation
{
public UnityExecutionContext Context;
public Action Action;
public long Tick;
public double Time;
public Func Predicate;
}
}
}