public TimeBudgetException(TimeSpan budget, Entity.TimeTrace trace) { this.budget = budget; this.t = trace; }
public List <EntityError> Evolve(IReadOnlyList <Entity> entities, Dictionary <Guid, ClientMessage[]> clientMessages, InconsistencyCoverage ic, TimeSpan budget, EntityChange.ExecutionContext ctx) { if (ic.Size != InconsistencyCoverage.CommonResolution) { throw new IntegrityViolation("Trying to evolve with an IC of size " + ic.Size + ". Should be " + InconsistencyCoverage.CommonResolution); } int numErrors = 0; List <Task> tasks = new List <Task>(); List <Entity.TimeTrace> tables = new List <Entity.TimeTrace>(); ClientMessage[] clientBroadcasts = null; if (clientMessages != null) { clientMessages.TryGetValue(Guid.Empty, out clientBroadcasts); } Stopwatch watch0 = new Stopwatch(); object lazyLock = new object(); bool exceeded = false; var rs = new LazyList <EntityError>(); Parallel.For(0, entities.Count, i => { Entity e = entities[i]; ClientMessage[] messages = null; if (clientMessages != null) { clientMessages.TryGetValue(e.ID.Guid, out messages); } var t = new Entity.TimeTrace(watch0); //tables.Add(t); EntityLogic st = null; try { if (!exceeded) { st = e.Evolve(t, this, Helper.Concat(clientBroadcasts, messages), ctx, ic.IsInconsistentR(ctx.LocalSpace.Relativate(e.ID.Position))); if (e.transientDeserializedLogic != null) { throw new IntegrityViolation("Transient deserialized logic was not wiped"); } } if (exceeded || watch0.Elapsed > budget) { exceeded = true; throw new TimeBudgetException(budget, t); } } catch (AssertFailedException) { throw; } catch (Exception ex) { if (st == null) { st = (EntityLogic)Helper.Deserialize(e.SerialLogicState); } var error = new EntityError(e, st, ex); lock (lazyLock) rs.Add(error); ic.FlagInconsistentR(ctx.LocalSpace.Relativate(e.ID.Position)); Interlocked.Increment(ref numErrors); } }); /* * * watch0.Start(); * foreach (var e in entities) * { * EntityMessage[] messages = null; * if (clientMessages != null) * { * clientMessages.TryGetValue(e.ID.Guid, out messages); * } * var t = new Entity.TimeTrace(watch0); * tables.Add(t); * tasks.Add(e.EvolveAsync(t,this, roundNumber, maySendMessages,Helper.Concat(clientBroadcasts, messages))); * } * int at = 0; * * Stopwatch watch = new Stopwatch(); * watch.Start(); * * LazyList<EntityEvolutionException> rs = new LazyList<EntityEvolutionException>(); * * foreach (var e in entities) * { * try * { * var remaining = (budget - watch.Elapsed).NotNegative(); * if (!tasks[at].Wait( remaining)) * throw new ExecutionException(e.ID, "Failed to execute " + (EntityLogic)Helper.Deserialize(e.SerialLogicState)+" in "+remaining.TotalMilliseconds+" ms"); * } * catch (Exception ex) * { * rs.Add(new EntityEvolutionException(e, ex, tables[at])); * * ic.FlagInconsistentR(Simulation.MySpace.Relativate(e.ID.Position)); * * Interlocked.Increment(ref numErrors); * } * at++; * }*/ return(rs.InternalList); }