public SimFutureTask(TimeSpan ts, CancellationToken token, SimFuture <T> source) : base(() => { if (token.IsCancellationRequested) { throw new TaskCanceledException(); } if (!source.Completed) { throw new TimeoutException($"Promise timed out after {Moment.Print(ts)}"); } if (source.Error != null) { throw source.Error; } return(source.Result); }) { Deadline = ts; _token = token; _source = source; }
public void Run(Func <SimControl, Task> plan) { _haltError = null; var watch = Stopwatch.StartNew(); var reason = "none"; Debug(LogType.RuntimeInfo, $"{"start".ToUpper()}"); Rand.Reinitialize(0); using (var cluster = new SimCluster(Def, this)) { Schedule(_scheduler, TimeSpan.Zero, _factory.StartNew(async() => { var control = new SimControl(cluster, this); try { await plan(control); } catch (Exception ex) { Halt("Plan failed", ex); } })); try { var step = 0; while (true) { step++; var hasFuture = FutureQueue.TryGetFuture(out var o); if (!hasFuture) { reason = "died"; break; } if (o.Time > _time) { _time = o.Time; } switch (o.Item) { case Task t: o.Scheduler.Execute(t); break; default: throw new InvalidOperationException(); } if (_haltError != null || _haltMessage != null) { reason = "halt"; break; } if ((_time - _lastActivity) >= _maxInactiveTicks) { reason = "no activity " + Moment.Print(TimeSpan.FromTicks(_maxInactiveTicks)); break; } if (_steps >= MaxSteps) { reason = MaxSteps + " steps reached"; break; } if (_time >= MaxTicks) { reason = "max time"; break; } } } catch (Exception ex) { reason = "fatal"; _haltError = ex; Console.WriteLine("Fatal: " + ex); } finally { if (_folder != null) { Directory.Delete(_folder, true); } } watch.Stop(); var softTime = TimeSpan.FromTicks(_time); var factor = softTime.TotalHours / watch.Elapsed.TotalHours; if (_haltMessage != null) { reason = _haltMessage.ToUpper(); } Debug(LogType.RuntimeInfo, $"{reason.ToUpper()} at {softTime}"); if (_haltError != null) { var demystify = _haltError.Demystify(); Console.WriteLine(demystify.GetType().Name + ": " + demystify.Message); Console.WriteLine(demystify.StackTrace); } Console.WriteLine($"Simulated {Moment.Print(softTime)} in {_steps} steps."); Console.WriteLine($"Took {Moment.Print(watch.Elapsed)} of real time (x{factor:F0} speed-up)"); // statistics Console.WriteLine($"Stats: {FutureQueue.JumpCount} jumps, {cluster.Machines.Sum(m => m.Value.SocketCount)} sockets"); } }