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;
        }
示例#2
0
        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");
            }
        }