using System; using System.Collections.Generic; namespace Ariadne.UnitTests { /// /// The context the condition wait scripts run in, with the latches they wait on and a log they write to. /// public class LatchWorld { public readonly Latch Door = new Latch(); public readonly Latch Alarm = new Latch(); public readonly List Log = new List(); public TimeSpan Limit = TimeSpan.FromSeconds(1); } /// /// Waits for the door to be set, then logs. /// public partial class SingleLatchScript : Arc { protected override void Run(LatchWorld world) { world.Log.Add("start"); first: Wait(world.Door); world.Log.Add("door"); } } /// /// Waits for the door to be clear, then logs. /// public partial class ClearLatchScript : Arc { protected override void Run(LatchWorld world) { world.Log.Add("start"); first: Wait(!world.Door); world.Log.Add("clear"); } } /// /// Waits for the door three times, with a local counting the trips. /// public partial class LoopedLatchScript : Arc { protected override void Run(LatchWorld world) { int count = 0; while (count < 3) { spin: Wait(world.Door); ++count; world.Log.Add("door " + count); } } } /// /// Waits for the door, then sleeps for a long time. /// public partial class LatchThenSleepScript : Arc { protected override void Run(LatchWorld world) { first: Wait(world.Door); world.Log.Add("door"); nap: Wait(TimeSpan.FromSeconds(100)); world.Log.Add("rested"); } } /// /// Waits for the door or the limit, and logs which came first. /// public partial class TimedLatchScript : Arc { protected override void Run(LatchWorld world) { first: Condition got = Wait(world.Door, timeout: world.Limit); world.Log.Add(got == world.Door ? "door" : "timeout"); } } /// /// Waits for the door to be clear or the limit, and logs which came first. /// public partial class TimedClearScript : Arc { protected override void Run(LatchWorld world) { first: Condition got = Wait(!world.Door, timeout: world.Limit); world.Log.Add(got == null ? "timeout" : "clear"); } } /// /// Waits for the door or the limit, then sleeps, so a late change to the door has to leave the sleep alone. /// public partial class TimedLatchThenSleepScript : Arc { protected override void Run(LatchWorld world) { first: Wait(world.Door, timeout: world.Limit); world.Log.Add("through"); nap: Wait(TimeSpan.FromSeconds(100)); world.Log.Add("rested"); } } /// /// Waits for the door unless told to skip it, and then sleeps, so a restart can send it past the wait. /// public partial class RestartableLatchScript : Arc { public bool Skip; protected override void Run(LatchWorld world) { if (!Skip) { first: Wait(world.Door); world.Log.Add("door"); } nap: Wait(TimeSpan.FromSeconds(100)); world.Log.Add("rested"); } } /// /// Waits for the door in a passage unless told to skip it, and then sleeps. /// public partial class RestartableLatchPassageScript : Arc { public bool Skip; private void Watch(LatchWorld world) { inner: Wait(world.Door); world.Log.Add("door"); } protected override void Run(LatchWorld world) { if (!Skip) { call: Watch(world); } nap: Wait(TimeSpan.FromSeconds(100)); world.Log.Add("rested"); } } /// /// Offers a passage for other arcs to run, which waits for the door. /// public partial class LatchLookoutScript : Arc { public void Watch(LatchWorld world) { watch: Wait(world.Door); world.Log.Add("door"); } protected override void Run(LatchWorld world) { } } /// /// Runs the passage of another arc that waits for the door, unless told to skip it, and then sleeps. /// public partial class LatchRelayScript : Arc { public LatchLookoutScript Lookout; public bool Skip; protected override void Run(LatchWorld world) { if (!Skip) { relay: Lookout.Watch(world); } nap: Wait(TimeSpan.FromSeconds(100)); world.Log.Add("rested"); } } /// /// Waits for either latch, and logs which one it was. /// public partial class AnyLatchScript : Arc { protected override void Run(LatchWorld world) { first: Condition got = WaitAny(world.Door, world.Alarm); world.Log.Add(got == world.Alarm ? "alarm" : "door"); } } /// /// Waits for the door to be set or clear, which is always so. /// public partial class AnyOrInverseScript : Arc { protected override void Run(LatchWorld world) { first: WaitAny(world.Door, !world.Door); world.Log.Add("through"); } } /// /// Waits for either latch, then sleeps, so a late change to either has to leave the sleep alone. /// public partial class AnyLatchThenSleepScript : Arc { protected override void Run(LatchWorld world) { first: WaitAny(world.Door, world.Alarm); world.Log.Add("through"); nap: Wait(TimeSpan.FromSeconds(100)); world.Log.Add("rested"); } } /// /// Waits for both latches, and logs what the wait returned. /// public partial class AllLatchesScript : Arc { protected override void Run(LatchWorld world) { first: Condition last = WaitAll(world.Door, world.Alarm); world.Log.Add(last == world.Alarm ? "all set" : "other"); } } /// /// Waits for the door to be set and the alarm to be clear. /// public partial class DoorOpenAlarmClearScript : Arc { protected override void Run(LatchWorld world) { first: WaitAll(world.Door, !world.Alarm); world.Log.Add("ready"); } } /// /// Waits for the door to be both set and clear, which can't happen. /// public partial class ContradictoryAllScript : Arc { protected override void Run(LatchWorld world) { first: WaitAll(world.Door, !world.Door); world.Log.Add("never"); } } /// /// Waits for either latch or the limit, and logs which came first. /// public partial class TimedAnyLatchScript : Arc { protected override void Run(LatchWorld world) { first: Condition got = WaitAny(timeout: world.Limit, world.Door, world.Alarm); world.Log.Add(got == null ? "timeout" : got == world.Alarm ? "alarm" : "door"); } } /// /// Waits for both latches or the limit, and logs which came first. /// public partial class TimedAllLatchesScript : Arc { protected override void Run(LatchWorld world) { first: Condition got = WaitAll(world.Limit, world.Door, world.Alarm); world.Log.Add(got == null ? "timeout" : "all set"); } } /// /// Takes the condition a wait ended on into a field it assigned earlier. /// public partial class AssignedLatchScript : Arc { public Condition Last; protected override void Run(LatchWorld world) { first: Last = Wait(world.Door, timeout: world.Limit); world.Log.Add(Last == null ? "timeout" : "door"); } } /// /// Returns the condition a wait ended on from a passage. /// public partial class ReturnedLatchScript : Arc { protected override void Run(LatchWorld world) { call: Condition got = Pick(world); world.Log.Add(got == null ? "timeout" : "door"); } private Condition Pick(LatchWorld world) { inner: return Wait(world.Door, timeout: world.Limit); } } }